1
0
mirror of https://github.com/mt-mods/led_marquee.git synced 2025-06-28 14:26:18 +02:00

11 Commits

Author SHA1 Message Date
b9a0656407 Added a "cursor position" command byte
updated README
2018-08-16 02:25:31 -04:00
4bb68ec009 basic multi-line support
Stack up a wall of LED panels, any horizontal and vertical amount

Set a channel on the upper left panel, leave the others un-set, and
connect a LuaC to it via digilines.

Long strings sent to that channel will be displayed using all panels,
starting at the upper-left and working from left to right, top to
bottom, wrapping from line to line as appropriate (similar to printing
to a shell terminal).

string.char(28) can be inserted anywhere to force a linefeed.

As usual, printing continues from node to node until the program either
finds a panel with a different non-empty channel than the first one, or
it finds a panel that's facing the wrong way.

If the program finds something other than a panel, it wraps to the next
line.  If it finds something other than a panel twice in a row, that
signals that text has wrapped off of the last row, and printing is cut
off.

Lines of panels don't need to be the same length, the program will wrap
as needed.

This commit also gets rid of the end-of-line padding, uses proper
string.rep() to create the all-off and all-on fills (each of which is
1kB), and fixes one or two other minor issues.

Strings are trimmed to 1 kB.

Panels are not erased between prints.
2018-08-16 01:46:03 -04:00
161623e869 fix minor mesh/triangulation glitch 2018-08-15 19:51:53 -04:00
d182766236 reduce color palette to 28 entries to make room for future control codes
(loses a dupe brown entry, and light blue and pink, which don't really work
well on a LED display)
2018-08-15 19:32:56 -04:00
09e5607d7a fix typo in docs 2018-08-15 19:17:39 -04:00
b9dd38c0de re-format palette to power-of-2 resolution 2018-08-15 19:05:05 -04:00
4fa6d54a4b fix undefined fdir in one spot
make some vars more readable
consolidate/cache fdir usage
2018-08-15 18:53:58 -04:00
157e517663 rename palette 2018-08-15 18:35:29 -04:00
e622f94dfc Merge branch 'led_marquee_gettext' into 'master'
Change intlib Getter (deprecated) to make_gettext_pair.

See merge request VanessaE/led_marquee!1
2018-08-15 22:13:43 +00:00
be7f72dfeb remove unused global 2018-08-15 18:12:35 -04:00
b33de7a530 Change intlib Getter (deprecated) to make_gettext_pair. 2018-08-15 10:09:30 -07:00
7 changed files with 142 additions and 88 deletions

View File

@ -16,9 +16,19 @@ The string will spread down the line until either a panel is found that faces th
Panels to the left of the connected one are ignored (unless they, too, have their own connections).
You can put multiple lines of panels end to end to form independent displays, so long as the panels that start each of the lines have unique channel names set.
You can also stack up a wall of LED panels, of any horizontal and vertical amount. If you then set a channel on the upper left panel, leave the others un-set, and connect a LuaController to it via digilines, the whole wall of panels will be treated as a multi-line display.
Long strings sent to that channel will be displayed starting at the upper-left and working from left to right, top to bottom, wrapping from line to line as appropriate (similar to printing to a shell terminal).
The string is padded with spaces and then trimmed to 64 characters.
As with a single line, printing continues from node to node until the program either finds a panel with a different non-empty channel than the first one, or if it finds a panel that's facing the wrong way.
If the program finds something other than a panel, it wraps to the next line. If it finds something other than a panel twice in a row, that signals that text has wrapped off of the last row, and printing is cut off.
Lines of panels don't need to be all the same length, the program will wrap as needed, with the left margin always being aligned with the panel the LuaController is connected to.
Strings are trimmed to 1 kB.
Panels are not erased between prints.
Any unrecognized symbol or character, whether part of a string or singularly is ignored, except as noted below.
@ -40,16 +50,20 @@ The panels also respond to these control messages:
* "off_multi" turns all panels in a lineup off
* "allon_multi" turns on all LEDs of all panels in a lineup.
A byte value of 0 to 30 will change colors (i.e. string.char(0 to 30) ). Color values 0 to 11 are:
A byte value of 0 to 27 will change colors (i.e. string.char(0 to 27) ). Color values 0 to 11 are:
Red (0), orange, yellow, lime, green, aqua, cyan, sky blue, blue, violet, magenta, or red-violet (11)
Colors 12 to 23 are the same as 0 to 11, but lower brightness.
Colors 23 - 30 are white, light grey, medium grey, dim grey, light blue, brown, and pink.
Colors 24 - 27 are white, light grey, medium grey, and dim grey.
The left-most/"master" panel will remember the last color used, and defaults to red.
A byte value of 28 will act as a line feed (I would have used 10, but that's a color code :-P )
A byte value of 29 signals a cursor position command. The next two byte values select a column and row, respectively. The next character after the row byte will be printed there, and the rest of the string then continues printing from that spot onwards.
You can use "get" and "getstr" to read the one character from the connected panel. These messages will not read the other panels in the lineup.
All panels emit a small amount of light when displaying something.

118
init.lua
View File

@ -1,11 +1,9 @@
-- simple LED marquee mod
-- by Vanessa Dannenberg
led_marquee = {}
local S
if minetest.get_modpath("intllib") then
S = intllib.Getter()
S = intllib.make_gettext_pair()
else
S = function(s) return s end
end
@ -44,41 +42,68 @@ local cbox = {
wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 }
}
local padding = " "
local allon = string.char(128)
for i = 1, 64 do
padding = padding.." "
allon = allon..string.char(144)
end
local display_string = function(pos, channel, string)
if string == "off_multi" then
string = ""
string = string.rep(" ", 1024)
elseif string == "allon_multi" then
string = allon
string = string.rep(string.char(144), 1024)
end
local padded_string = string.sub(string..padding, 1, 64)
local fdir = minetest.get_node(pos).param2 % 8
local pos2 = pos
local mastermeta = minetest.get_meta(pos)
local lastcolor = mastermeta:get_int("lastcolor")
if not lastcolor or lastcolor < 0 or lastcolor > 30 then
lastcolor = 0
mastermeta:set_int("lastcolor", 0)
string = string.sub(string, 1, 1024)
local master_fdir = minetest.get_node(pos).param2 % 8
local master_meta = minetest.get_meta(pos)
local last_color = master_meta:get_int("last_color")
local pos2 = table.copy(pos)
if not last_color or last_color < 0 or last_color > 27 then
last_color = 0
master_meta:set_int("last_color", 0)
end
for i = 1, 64 do
local i = 1
local len = string.len(string)
local wrapped = nil
while i <= len do
local node = minetest.get_node(pos2)
local fdir = node.param2 % 8
local meta = minetest.get_meta(pos2)
local setchan = meta:get_string("channel")
if not string.match(node.name, "led_marquee:char_") or (setchan ~= nil and setchan ~= "" and setchan ~= channel) then break end
local asc = string.byte(padded_string, i, i)
if (node.param2 % 8) == fdir and asc > 30 and asc < 256 then
minetest.swap_node(pos2, { name = "led_marquee:char_"..asc, param2 = (node.param2 % 8) + (lastcolor*8)})
local setchan = nil
if meta then setchan = meta:get_string("channel") end
local asc = string.byte(string, i, i)
if not string.match(node.name, "led_marquee:char_") then
if not wrapped then
pos2.x = pos.x
pos2.y = pos2.y-1
pos2.z = pos.z
wrapped = true
else
break
end
elseif string.match(node.name, "led_marquee:char_")
and fdir ~= master_fdir or (setchan ~= nil and setchan ~= "" and setchan ~= channel) then
break
elseif asc == 28 then
pos2.x = pos.x
pos2.y = pos2.y-1
pos2.z = pos.z
i = i + 1
wrapped = nil
elseif asc == 29 then
local c = string.byte(string, i+1, i+1) or 0
local r = string.byte(string, i+2, i+2) or 0
pos2.x = pos.x + (fdir_to_right[fdir+1][1])*c
pos2.y = pos.y - r
pos2.z = pos.z + (fdir_to_right[fdir+1][2])*c
i = i + 3
wrapped = nil
elseif asc > 30 and asc < 256 then
minetest.swap_node(pos2, { name = "led_marquee:char_"..asc, param2 = master_fdir + (last_color*8)})
pos2.x = pos2.x + fdir_to_right[fdir+1][1]
pos2.z = pos2.z + fdir_to_right[fdir+1][2]
elseif asc < 31 then
lastcolor = asc
mastermeta:set_int("lastcolor", asc)
i = i + 1
wrapped = nil
elseif asc < 28 then
last_color = asc
master_meta:set_int("last_color", asc)
i = i + 1
wrapped = nil
end
end
end
@ -86,37 +111,38 @@ end
local on_digiline_receive_string = function(pos, node, channel, msg)
local meta = minetest.get_meta(pos)
local setchan = meta:get_string("channel")
local lastcolor = meta:get_int("lastcolor")
if not lastcolor or lastcolor < 0 or lastcolor > 30 then
lastcolor = 0
meta:set_int("lastcolor", 0)
local last_color = meta:get_int("last_color")
if not last_color or last_color < 0 or last_color > 27 then
last_color = 0
meta:set_int("last_color", 0)
end
local fdir = node.param2 % 8
if setchan ~= channel then return end
if msg and msg ~= "" and type(msg) == "string" then
if string.len(msg) > 1 then
if msg == "off" then
minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = fdir + (last_color*8)})
elseif msg == "colon" then
minetest.swap_node(pos, { name = "led_marquee:char_58", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_58", param2 = fdir + (last_color*8)})
elseif msg == "period" then
minetest.swap_node(pos, { name = "led_marquee:char_46", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_46", param2 = fdir + (last_color*8)})
elseif msg == "del" then
minetest.swap_node(pos, { name = "led_marquee:char_127", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_127", param2 = fdir + (last_color*8)})
elseif msg == "allon" then
minetest.swap_node(pos, { name = "led_marquee:char_144", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_144", param2 = fdir + (last_color*8)})
elseif msg == "cursor" then
minetest.swap_node(pos, { name = "led_marquee:char_31", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_31", param2 = fdir + (last_color*8)})
else
display_string(pos, channel, msg)
end
else
local asc = string.byte(msg)
if asc > 30 and asc < 256 then
minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = (node.param2 % 8) + (lastcolor*8)})
elseif asc < 31 then
lastcolor = asc
meta:set_int("lastcolor", asc)
minetest.swap_node(pos, { name = "led_marquee:char_"..asc, param2 = fdir + (last_color*8)})
elseif asc < 28 then
last_color = asc
meta:set_int("last_color", asc)
elseif msg == "get" then -- get value as ASCII numerical value
digiline:receptor_send(pos, digiline.rules.default, channel, tonumber(string.match(minetest.get_node(pos).name,"led_marquee:char_(.+)"))) -- wonderfully horrible string manipulaiton
elseif msg == "getstr" then -- get actual char
@ -125,9 +151,9 @@ local on_digiline_receive_string = function(pos, node, channel, msg)
end
elseif msg and type(msg) == "number" then
if msg == 0 then
minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_32", param2 = fdir + (last_color*8)})
elseif msg > 30 then
minetest.swap_node(pos, { name = "led_marquee:char_"..tostring(msg), param2 = (node.param2 % 8) + (lastcolor*8)})
minetest.swap_node(pos, { name = "led_marquee:char_"..tostring(msg), param2 = fdir + (last_color*8)})
end
end
end
@ -164,7 +190,7 @@ for i = 31, 255 do
drawtype = "mesh",
mesh = "led_marquee.obj",
tiles = tiles,
palette="palette.png",
palette="led_marquee_palette.png",
use_texture_alpha = true,
groups = groups,
paramtype = "light",

Binary file not shown.

Binary file not shown.

View File

@ -25,12 +25,7 @@ v 0.500000 -0.449125 -0.468750
v -0.500000 -0.449125 -0.468750
v -0.500000 -0.449125 0.468750
v 0.500000 -0.449125 0.468750
vt 0.667843 0.000000
vt 0.667843 0.015513
vt 0.681855 0.031026
vt 0.681855 0.961799
vt 0.667843 0.977312
vt 0.667843 0.992824
vt 0.723891 0.992824
vt 0.723891 0.000000
vt 1.000000 0.007175
@ -39,32 +34,37 @@ vt 0.103234 1.000000
vt 0.103234 0.007175
vt 0.723891 0.000000
vt 0.723891 0.992824
vt 0.667843 0.992824
vt 0.667843 0.977312
vt 0.681855 0.961799
vt 0.681855 0.031026
vt 0.003280 0.226388
vt 0.900045 0.226388
vt 0.900045 0.164337
vt 0.003280 0.164337
vt 0.900045 0.226388
vt 0.003280 0.226388
vt 0.003280 0.164337
vt 0.900045 0.164337
vt 1.000000 0.017400
vt 0.000000 -0.000000
vt 1.000000 -0.000000
vt 1.000000 1.000000
vt 0.000000 0.982506
vt 1.000000 0.982506
vt 0.000000 0.965011
vt 0.000000 0.034801
vt 1.000000 0.034801
vt 0.667843 0.992824
vt 0.681855 0.961799
vt 0.667843 0.977312
vt 0.667843 0.015513
vt 0.667843 0.000000
vt 0.003280 0.226388
vt 0.900045 0.226388
vt 0.900045 0.164337
vt 0.003280 0.164337
vt 0.900045 0.226388
vt 0.003280 0.226388
vt 0.003280 0.164337
vt 0.900045 0.164337
vt 1.000000 -0.000000
vt 1.000000 0.017400
vt 0.667843 0.000000
vt 0.681855 0.031026
vt 0.667843 0.015513
vt 0.667843 0.977312
vt 0.667843 0.992824
vt 0.000000 0.017400
vt 0.000000 -0.000000
vt 1.000000 0.982506
vt 1.000000 1.000000
vt 0.000000 1.000000
vt 0.000000 0.982506
vt 0.000000 0.965011
vt 1.000000 0.965011
vt 1.000000 0.034801
vt 0.000000 0.034801
vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
@ -73,25 +73,39 @@ vt 0.000000 0.000000
vt 1.000000 0.000000
vt 1.000000 1.000000
vt 0.000000 1.000000
vn 1.0000 0.0000 -0.0000
vn 0.0000 -1.0000 0.0000
vn 1.0000 0.0000 0.0000
vn 0.0000 -1.0000 -0.0000
vn -1.0000 0.0000 0.0000
vn -0.0000 -0.0000 -1.0000
vn 0.0000 0.0000 1.0000
vn 0.0000 0.0000 -1.0000
vn -0.0000 0.0000 1.0000
vn -0.0000 1.0000 0.0000
vn -0.0000 0.7071 -0.7071
vn -0.0000 0.7071 0.7071
g Cube_Cube_LEDs_Cube_Cube_LEDs_base
s off
f 5/1/1 6/2/1 7/3/1 8/4/1 9/5/1 10/6/1 11/7/1 12/8/1
f 12/9/2 11/10/2 13/11/2 14/12/2
f 14/13/3 13/14/3 15/15/3 16/16/3 17/17/3 18/18/3 19/19/3 20/20/3
f 12/21/4 14/22/4 20/23/4 5/24/4
f 13/25/5 11/26/5 10/27/5 15/28/5
f 20/29/6 19/30/6 6/31/6 5/32/6
f 16/33/6 15/34/6 10/35/6 9/36/6
f 9/36/7 8/37/7 17/38/7 16/33/7
f 18/39/8 7/40/8 6/31/8 19/30/8
f 8/1/1 11/2/1 12/3/1
f 12/4/2 11/5/2 13/6/2 14/7/2
f 14/8/3 13/9/3 18/10/3
f 12/11/4 14/12/4 20/13/4 5/14/4
f 13/15/5 11/16/5 10/17/5 15/18/5
f 19/19/6 5/20/6 20/21/6
f 15/22/6 9/23/6 16/24/6
f 8/25/7 16/24/7 9/23/7
f 7/26/8 19/19/8 18/27/8
f 13/9/3 15/28/3 17/29/3
f 15/28/3 16/30/3 17/29/3
f 19/31/3 20/32/3 18/10/3
f 20/32/3 14/8/3 18/10/3
f 13/9/3 17/29/3 18/10/3
f 12/3/1 5/33/1 7/34/1
f 5/33/1 6/35/1 7/34/1
f 9/36/1 10/37/1 8/1/1
f 10/37/1 11/2/1 8/1/1
f 12/3/1 7/34/1 8/1/1
f 7/26/8 6/38/8 19/19/8
f 19/19/6 6/38/6 5/20/6
f 15/22/6 10/39/6 9/23/6
f 8/25/7 17/40/7 16/24/7
g Cube_Cube_LEDs_Cube_Cube_LEDs_leds_off
f 1/41/6 2/42/6 3/43/6 4/44/6
g Cube_Cube_LEDs_Cube_Cube_LEDs_leds_on

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 B