Advertisement
rollton

Paint на проекторе

Feb 2nd, 2018
231
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 11.53 KB | None | 0 0
  1. --- Можн улучшить:
  2. -- [кря] Сейчас при установке проектора он поворачивается всегда на сервер, но можно этого не делать, заменив алагаритм нахождения пикселей при нажатии мечём заменив оси, учтённые при установке
  3.  
  4. -- TODO
  5. -- Разобраться с зоной вокруг проектора
  6.  
  7. local component, fs, serializ, event = require("component"), require("filesystem"), require("serialization"), require("event")
  8.  
  9. local args = require("shell").parse(...)
  10. local user = ({event.pull()})[5] -- Ник того, кто запустил эту программу
  11.  
  12. local nameSaveCFG, FileCfg , cfg = "/home/HoloSave.cfg", "/home/HoloEditor.cfg"
  13. cfg = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
  14.  
  15. local sensor = component.openperipheral_sensor
  16.  
  17. function hologramAdd()
  18.     print("Первичная колибровка, установите проектор")
  19.     repeat until ({event.pull("component_added")})[3] == "hologram" -- TODO при файле конфига не запускает
  20.     result = component.hologram
  21.  
  22.     result.setRotation(math.floor(sensor.getPlayerByName(user).all().living.yawHead/90+0.5)*90-180,0,1,0)
  23.     --result.setTranslation(0,5,0)
  24.     return result
  25. end
  26.  
  27. local hologram = component.isAvailable("hologram") and component.hologram or hologramAdd()
  28.  
  29. local set = hologram.set
  30.  
  31. -- цвет, режим линии, шаг для кнопки "шаг назад", сам буфер, буфер кнопок, undo , относительные координаты Hologram к Sensor, переменная отвечающая за отображение всех кнопок
  32. local color, line, un, buf, buttons, undoBuf, w, fl = 2, 0, 0, {}, {}, {}, {}, {}
  33.  
  34. local function add(mas,x,y,z,f)
  35.     mas[x] = mas[x] or {}
  36.     mas[x][y] = mas[x][y] or {}
  37.     mas[x][y][z] = f
  38. end
  39.  
  40. local function read(x,y,z) return buf[x] and buf[x][y] and buf[x][y][z] end -- Считывание буфера
  41.  
  42. local xxx,yyy,zzz,ccol
  43. local function hologramSet(xx,yy,zz,col) -- Ставим пиксель
  44.     if line ~= 0 and xxx == xx and yyy == yy and zzz == zz and ccol == ccol then return end
  45.  
  46.     add(buf,xx,yy,zz, col ~= 0 and col or nil )
  47.     set(xx,yy,zz,col or 0)
  48.     xxx,yyy,zzz,ccol = xx,yy,zz,col
  49. end
  50.  
  51. local xS, yS, zS
  52.  
  53. local Scale = hologram.getScale()
  54. local sizeRadiusHologram, stepFromHologram = Scale*1.5 , 2
  55. local zone = sizeRadiusHologram + stepFromHologram
  56.  
  57. local function search(name) -- Возвращает данные о расположении игрока относительно координатной плоскости проектора, а так же направление взгляда
  58.     local player
  59.     pcall(function() player = sensor.getPlayerByName(name) end) -- Бывает выдаёт ошибки, поэтому засунул в pcall (name or "" не помогает)
  60.     if player then
  61.         player = player.all()
  62.         local p = player.position
  63.         p.x, p.y, p.z = p.x - w.x , p.y - w.y, p.z - w.z
  64.         if (p.x > -zone) and (p.x < zone) and (p.z > -zone) and (p.z < zone) and (p.y > -Scale) and (p.y < zone*2) then
  65.  
  66.             local sneaking = player.living.isSneaking
  67.  
  68.             local growth = sneaking and 1.54 or 1.62 -- player growth
  69.             p.x, p.y, p.z = (p.x + sizeRadiusHologram)/Scale, (p.y-Scale*2+growth-0.003)/Scale, (p.z + sizeRadiusHologram)/Scale -- Смещение к начальным координатам галограммы
  70.             if player.player.isBlocking then
  71.                 local xH, yH, zH = p.x*16+1,(p.y)*16+1,p.z*16+1 -- Entry points on the hologram
  72.  
  73.                 local yawHead, pitch = math.rad( player.living.yawHead ) , math.rad( player.living.pitch )
  74.                 local dx, dy, dz = -math.sin( yawHead )/48 , -math.tan( pitch )/48 , math.cos( yawHead )/48
  75.  
  76.                 dy = dy > 1 and 1 or dy < -1 and -1 or dy -- Решение проблемы с появлением интвервала между пикселей при рисовании линий под 90 градусов относительно горизонта (голову резко вверх или виз)
  77.                 if dy == 1 or dy == -1 then dx, dz = 0,0 end
  78.  
  79.                 return xH, yH, zH, dx, dy, dz, sneaking
  80.             end
  81.         end
  82.     end
  83. end
  84.  
  85. local function main(name)
  86.  
  87.     local xH, yH, zH, dx, dy, dz, sneaking = search(name)
  88.     if not xH then return end
  89.  
  90.     local xS, yS, zS = xH, yH, zH
  91.     local flag,undoMiniBuf,xL,yL,zL,x,y,z = true,{}
  92.                
  93.     repeat
  94.         xH, yH, zH = xH + dx, yH + dy, zH + dz
  95.         x,y,z = math.floor(xH) , math.floor(yH) , math.floor(zH)
  96.        
  97.         if (fl ~= 0 and buttons[x] and buttons[x][y] and buttons[x][y][z]) or (x == 1 and y == 32 and z == 1) then -- Buttons или столкновение
  98.             buttons[x][y][z]()
  99.             flag = false
  100.             break
  101.         end
  102.  
  103.         if read(x,y,z) and (x < 48 and y < 48 and z < 48 and x > 1 and y > 1 and z > 1 ) then -- Pixel
  104.             if sneaking then -- Нажал Shift?
  105.                 if line == 0 then -- Выключена отрисовка линий?
  106.                     xxx = 0 -- <>
  107.                     x,y,z = math.floor(xH-dx),math.floor(yH-dy),math.floor(zH-dz)
  108.                     hologramSet(x,y,z,color)  -- Set Pixel
  109.                     table.insert(undoMiniBuf,{color,x,y,z, true})
  110.                     break
  111.                 else
  112.                     xL,yL,zL = x,y,z
  113.                     break
  114.                 end
  115.             else
  116.                 xxx = 0 -- <>
  117.                 table.insert(undoMiniBuf,{read(x,y,z),x,y,z, false})
  118.                 hologramSet(x,y,z,0) -- Delete Pixel
  119.                 flag = false
  120.                 break
  121.             end
  122.         end
  123.     until x > 80 or y > 64 or z > 80 or x < -32 or y < -16 or z < -32
  124.    
  125.     if flag and line ~= 0 and sneaking then
  126.         xH, yH, zH = xS, yS, zS
  127.         x,y,z = 0,0,0
  128.         repeat
  129.         -- while not((x > 48 or y > 48 or z > 48 or x < 1 or y < 1 or z < 1) or (x == xL and y == yL and z == zL)) do
  130.         --while (x < 48 or y < 48 or z < 48 or x > 1 or y > 1 or z > 1) and (x ~= xL and y ~= yL and z ~= zL) do
  131.             xH, yH, zH = xH + dx, yH + dy, zH + dz
  132.             x,y,z = math.floor(xH) , math.floor(yH) , math.floor(zH)
  133.             hologramSet(x,y,z,line)
  134.             table.insert(undoMiniBuf,{color,x,y,z, true})
  135.         --end
  136.         until (x > 48 or y > 48 or z > 48 or x < 1 or y < 1 or z < 1) or (x == xL and y == yL and z == zL)
  137.     end
  138.  
  139.     if #undoMiniBuf > 0 then
  140.         un = un + 1 > 40 and 1 or un + 1
  141.         undoBuf[un] = undoMiniBuf
  142.  
  143.         local saveCFG = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
  144.         for _,v in pairs(undoMiniBuf) do -- Сохранение рисунка
  145.             add(saveCFG,v[2],v[3],v[4],v[5] and v[1] or nil )
  146.         end
  147.         io.open(nameSaveCFG,"w"):write(serializ.serialize(saveCFG)):close()
  148.     end
  149. end
  150.  
  151. local function editScale(inc)
  152.     if Scale+inc<1 and Scale+inc>4 then inc = 0 end
  153.     Scale = Scale+inc/10
  154.     hologram.setScale(Scale)
  155.     sizeRadiusHologram, stepFromHologram = Scale*1.5 , 2
  156.     zone = sizeRadiusHologram + stepFromHologram
  157. end
  158.  
  159. local function start() -- Первичная калибровка координат сенсора и голограммы
  160.     hologram.setScale(1)
  161.     hologram.setTranslation(0,0.5,0)
  162.     editScale(0)
  163.     w.n = 0
  164.     for _,_ in component.list("hologram") do w.n = w.n + 1 end
  165.     if w.n == 1 then
  166.         print("Встав на голографический проектор, нажмите Enter")
  167.     else -- да я да я да
  168.         if w.n == 4 or w.n == 8 then
  169.             print("Встав между голографическими проекторами, нажмите Enter")
  170.         else
  171.             print("Найдено иное количество проекторов, отличающиеся от 1/4/8 шт ")
  172.         end
  173.     end
  174.     local ev
  175.     repeat ev = {event.pull("key_down")} until ev[3] == 13
  176.     local playerPoz = sensor.getPlayerByName(ev[5]).all().position
  177.     w.x, w.y, w.z = playerPoz.x, playerPoz.y, playerPoz.z
  178.     if w.n == 1 or w.n == 8 then w.x, w.y, w.z = math.floor(w.x)+0.5, math.floor(w.y)-0.5, math.floor(w.z)+0.5 end
  179.     if w.n == 4 then w.x, w.y, w.z = math.floor(w.x+0.5), math.floor(w.y+0.5), math.floor(w.z+0.5) end
  180.     io.open(FileCfg,"w"):write(serializ.serialize(w)):close()
  181.     print("При изменении положения сенсора или голограммы, либо запустите программу с параметром reset либо удалите файл HoloEditor.cfg , тогда колибровка запустится вновь")
  182. end
  183.  
  184. local function setButtons(col) -- Выводим кнопки на экран
  185.     for x,v1 in pairs(buttons) do
  186.         for y,v2 in pairs(v1) do
  187.             for z,_ in pairs(v2) do
  188.                 set(x,y,z,col)
  189.             end
  190.         end
  191.     end
  192.     for i=2,3 do set(i,5,1,line) end -- анимированная кнопка линии
  193. end
  194.  
  195. local function clearHologram()
  196.     hologram.clear()
  197.     for z = 23,25 do
  198.         for x = 23,25 do
  199.             hologramSet(x,16,z,z-22)
  200.         end
  201.     end
  202.     setButtons(color)
  203.     if fs.exists(nameSaveCFG) then io.open(nameSaveCFG,"w"):write("{}"):close() end -- Стираем буфер сохранения
  204. end
  205.  
  206. local function LineFun() -- Изменения состояния кисти "Линия" и анимация кнопки
  207.     line = line==color and 0 or color
  208.     for i=2,3 do set(i,5,1,line) end
  209. end --<>
  210.  
  211. local function undo() -- Шаг назад
  212.     if undoBuf[un] ~= nil then
  213.         local saveCFG = fs.exists(nameSaveCFG) and serializ.unserialize(io.open(nameSaveCFG):read()) or {}
  214.  
  215.         for _,v in pairs( undoBuf[un] ) do
  216.             hologramSet(v[2],v[3],v[4],v[5] and 0 or v[1])
  217.             add(saveCFG,v[2],v[3],v[4],v[5] and 0 or v[1])
  218.         end
  219.         undoBuf[un] = nil
  220.         un = un-1 < 1 and 40 or un-1
  221.  
  222.         io.open(nameSaveCFG,"w"):write(serializ.serialize(saveCFG)):close()
  223.     end
  224. end
  225.  
  226. buttons = {
  227.     { { { 1,1,1 } } , function() color = color+1 > 3 and 1 or color+1 line = line == 0 and 0 or color set(1,1,1,color) setButtons(color) end}, -- Set color
  228.     { { { 1,3,1 } } , function() set(1,3,1,color) hologramSet(math.floor(xS), math.floor(yS), math.floor(zS),color) end}, -- Set pixel to player
  229.     { { { 1,5,1 } } , function() LineFun() set(1,5,1,color) end}, -- Line activation
  230.     { { { 2,5,1 }, { 3,5,1 } } , function() LineFun() end},
  231.     { { { 1,7,1 }, { 1,8,1 } } , function() undo() end},
  232.     { { { 2,10,2 }, { 2,12,2 }, { 1,11,3 }, { 3,11,1 } } , function() editScale(1) end},
  233.     { { { 2,14,2 }, { 1,14,3 }, { 3,14,1 } } , function() editScale(-1) end},
  234.     { { { 1,30,1 } } , function() buf = {} clearHologram() end},
  235.     { { { 1,32,1 } } , function() fl = fl==0 and color or 0 setButtons(fl) set(1,32,1,fl) end}
  236. }
  237.  
  238. local bibi = {}
  239. for _,v in pairs(buttons) do -- Хитрожопная система, по превращению массива кнопок в удобный массив для использования
  240.     for _,coords in pairs(v[1]) do
  241.         add(bibi,coords[1],coords[2],coords[3],v[2])
  242.     end
  243. end
  244. buttons = bibi
  245. bibi = nil
  246.  
  247. if fs.exists(FileCfg) then -- Файл настроек относительных координат проектора
  248.     w = serializ.unserialize(io.open(FileCfg):read())
  249.     if w.n == nil then print("Файл HoloEditor.cfg повреждён. Перезапустите программу") fs.remove(FileCfg) os.exit() end
  250. else
  251.     start()
  252. end
  253.  
  254. if cfg ~= nil and type(cfg) == "table" then
  255.     hologram.clear()
  256.  
  257.     for x,v1 in pairs(cfg) do -- Рисуем сохранённый рисунок из файла
  258.         for y,v2 in pairs(v1) do
  259.             for z,col in pairs(v2) do
  260.                 hologramSet(x,y,z,col)
  261.             end
  262.         end
  263.     end
  264.  
  265.     setButtons(color)
  266. else
  267.     clearHologram()
  268. end
  269.  
  270. while true do
  271.     if args[1] == "reset" then start() end
  272.     if args[1] and tonumber(args[1]) == nil then -- Если при запуске проги был указан ник, тогда не будет поиска
  273.         main(args[1])
  274.     else
  275.         for _,v in pairs( sensor.getPlayers() ) do
  276.             main(v.name)
  277.         end
  278.     end
  279.     os.sleep(0.0001)
  280. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement