forked from MoonlightOwl/Totoro-Bank
-
Notifications
You must be signed in to change notification settings - Fork 0
/
text_flow.lua
205 lines (192 loc) · 6.68 KB
/
text_flow.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
-- Text Flow (1.1)
-- by Totoro (c) 26/3/2015
local unicode = require('unicode')
local event = require('event')
local fs = require('filesystem')
local com = require("component")
local screen = com.screen
local gpu = com.gpu
-- константы
local DATAFILE = "data.txt"
local CONFIGFILE = "flow.ini"
-- сохраняем старое и ставим новое разрешение
local screenW, screenH = screen.getAspectRatio()
local oldW, oldH = gpu.getResolution()
local WIDTH, HEIGTH = math.ceil(screenW*4.5), screenH
-- другие нужные и полезные параметры
local scroll_delay = 0.2
-- ========================== L O A D F I L E S ========================== --
-- загружаем настройки и таблицу страниц
function loadConfig(configfile)
file = io.open(configfile, "r")
if file ~= nil then
pages = {}
for line in file:lines() do
-- если строка не пуста и не комментарий
if string.len(line) ~= 0 and line:sub(1,1) ~= "#" then
key, data = line:match("(%S+)%s*=%s*(.+)")
-- читаем скорость прокрутки
if key == "scroll" then
value = tonumber(data)
if value ~= nil then scroll_delay = value end
end
end
end
file:close()
else
-- файл конфигурации не найден
error("Файл конфигураций не найден!")
end
end
local colors = {}
colors.black = 0x000000
colors.white = 0xffffff
colors.gray = 0x888888
colors.red = 0xff0000
colors.green = 0x00ff00
colors.blue = 0x0000ff
colors.yellow = 0xffff00
colors.cyan = 0x00b6ff
-- эта функция читает всякую тарабарщину и пытается понять,
-- какой цвет имелся ввиду
function interpret(word)
-- если цвет есть в таблице
if colors[word] ~= nil then
return colors[word]
end
-- если его там нет
local color = 0
for i=1, 6 do
local n = string.byte(word:sub(i,i)) - 48
color = color * 16 + n
end
return color
end
local data = {}
local last_update = ""
function addToken(fore, back, text)
table.insert(data, {fore = fore, back = back, text = text, len = unicode.len(text)})
end
function loadData(filename)
local file = io.open(filename, 'r')
if file ~= nil then
-- текущий токен
local fore = 0xffffff
local back = 0x000000
local text = ""
-- очищаем таблицу и пускаем первой строкой разделитель
data = {}
data[0] = {fore = fore, back = back, text = " * * * ", len = 13}
-- начинаем читать файл посимвольно
while true do
local char = file:read(1)
-- если достигнут конец файла - выходим
if char == nil then
addToken(fore, back, text)
text = ""
break
end
-- если это не перенос строки (на которые программе чхать в принципе)
if char ~= '\n' and char ~= '\r' then
-- если это служебный символ - читаем все слово и интерпретируем его
if char == '#' or char == '@' then
-- сохраняем то что есть
if text ~= "" then
addToken(fore, back, text)
text = ""
end
-- читаем слово
local word = ""
while true do
local x = file:read(1)
if x == ' ' or x == nil or x == '\r' then break end
if x == '\n' then
-- завершаем строку
addToken(fore, back, text)
text = ""
-- ставим разделитель (белые звездочки)
table.insert(data, data[0])
break
end
word = word..x
end
local color = interpret(word)
if char == '#' then fore = color
else back = color end
-- иначе - добавляем к текущей строке
else
text = text .. char
end
elseif char == '\n' then
-- завершаем строку
addToken(fore, back, text)
text = ""
-- ставим разделитель (белые звездочки)
table.insert(data, data[0])
end
end
file:close()
last_update = fs.lastModified(filename)
end
end
-- проверяем, давно ли обновлялся текст в файле
function updateData(filename)
local stamp = fs.lastModified(filename)
if stamp ~= last_update then
loadData(filename)
end
end
-- ============================== R E N D E R ============================== --
local pos = {word = 0, letter = 1}
function drawFlow()
local len = 0
local word = pos.word
while len < WIDTH do
-- рисуем фрагменты строк, соответствующими цветами
gpu.setForeground(data[word].fore)
gpu.setBackground(data[word].back)
if len == 0 then
gpu.set(2+len-pos.letter, 1, data[word].text) --unicode.sub(data[word].text, pos.letter, -1))
len = len + data[word].len - pos.letter + 1
else
gpu.set(1+len, 1, data[word].text)
len = len + data[word].len
end
word = word + 1
if word > #data then
gpu.setForeground(data[0].fore)
gpu.setForeground(data[0].back)
gpu.set(len+1, 1, string.rep(' ', WIDTH-len))
break
end
end
-- двигаем текст
pos.letter = pos.letter + 1
if pos.letter > data[pos.word].len then
pos.letter = 1
pos.word = pos.word + 1
-- если список строк кончился - обновление и резет в начало
if pos.word > #data then
pos.word = 0
gpu.setForeground(data[0].fore)
gpu.setForeground(data[0].back)
gpu.set(1, 1, string.rep(' ', WIDTH))
updateData(DATAFILE)
end
end
end
-- ========================== M A I N C Y C L E ========================== --
-- инициализация
-- подгоняем разрешение монитора
gpu.setResolution(WIDTH, HEIGTH)
-- читаем конфиги
loadConfig(CONFIGFILE)
-- читаем текст
updateData(DATAFILE)
while true do
name = event.pull(scroll_delay)
if name == 'key_down' then break end
drawFlow()
end
-- восстановим разрешение
gpu.setResolution(oldW, oldH)