1
0
mirror of https://github.com/mt-mods/led_marquee.git synced 2025-06-28 22:36:41 +02:00

9 Commits

Author SHA1 Message Date
c647effff2 make µC and lamps optional depends
(they're only needed for crafting anyways)
2018-08-16 16:50:41 -04:00
ce9666cc48 local-ize functions 2018-08-16 13:22:02 -04:00
4d1d90cccc local-ize iso_chars 2018-08-16 13:21:28 -04:00
5ed4d1ef27 update README to follow 2018-08-16 13:20:26 -04:00
ee77614b97 treat strings prefixed with 0xff as Lua's weird UTF-8 encoding
translate them to bare ISO-8859-1 at print time

Only alters chars with codes > 0x9f, so graphics/symbols in the
0x7f-0x9f range and color and control codes < 0x20 are preserved

The routine assumes that any char code > 0x9f is the first byte of a
two-byte UTF-8 symbol.

Note that due to Minetest's busted formspecs, it's not possible to
actually type-in or copy-paste proper UTF strings to take advantage of
this mode, so it's only useful if the strings are generated by or
imported in from something else (e.g. a URL or something, or a LuaC
program that generates strings)
2018-08-16 13:14:27 -04:00
d0d127e837 rewrite README a bit, synchronize with forum post 2018-08-16 02:43:11 -04:00
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
6 changed files with 162 additions and 77 deletions

View File

@ -1,29 +1,35 @@
# LED marquee mod
*by Vanessa Dannenberg*
This mod provides set of alphanumeric LED marquee panels, controlled by Mesecons' Digilines mod. This mod provides set of alphanumeric LED marquee panels, controlled by Mesecons' Digilines mod.
Simply place a panel, right-click it, and set a channel. Simply place one or more panels, and set a channel on just the left-most or upper-left one.
Then send a character, a string, or one of several control words to that channel from a Mesecons Lua Controller and the mod will try to display it. The panels use the standard 7-bit ASCII character set (with a few alterations). Then send a character, a string, or one of several control words or codes to that channel from a Mesecons Lua Controller and the mod will try to display it.
A single character will be displayed on the connected panel. A numeric message (i.e. not a string) will display the first digit on the connected panel. A single character will be displayed on the connected panel. A numeric message (i.e. not a string) will display the first digit on the connected panel.
Strings will be displayed using all panels in a lineup, so long as they all face the same way, starting from the panel the Lua Controller is connected to, going left to right. The other panels in the line do not need to be connected to anything - think of them as being connected together internally. Only the panel at the far left need be connected to the Lua Controller. Strings will be displayed using all panels in a lineup, so long as they all face the same way, starting from the panel the Lua Controller is connected to, going left to right. The other panels in the line do not need to be connected to anything - think of them as being connected together internally. Only the panel at the far left need be connected to the Lua Controller.
The string will spread down the line until either a panel is found that faces the wrong way, or has a channel that's not empty/nil and is set to something other than what the first is set to, or if a node is encountered that is not an alpha-numeric panel at all. The string will spread down the line until either a panel is found that faces the wrong way, or has a channel that's not empty/nil and is set to something other than what the first is set to, or if a node is encountered that is not an alpha-numeric panel at all.
Panels to the left of the connected one are ignored (unless they, too, have their own connections). 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.
The string is padded with spaces and then trimmed to 64 characters. 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).
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 there.
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. Any unrecognized symbol or character, whether part of a string or singularly is ignored, except as noted below.
This mod uses the full ISO-8859-1 character set (see https://en.wikipedia.org/wiki/ISO/IEC_8859-1 for details), plus a bunch of symbols stuffed into the empty 128-159 range that should be useful on a marquee: This mod uses the full ISO-8859-1 character set (see https://en.wikipedia.org/wiki/ISO/IEC_8859-1 for details), plus a bunch of symbols stuffed into the normally-empty 128-159 range that should be useful on this sort of display:
* 128,129: musical notes * 128,129: musical notes
* 130-140: box drawing glyphs * 130-140: box drawing glyphs
* 141-144: block shades * 141-144: block shades
@ -31,26 +37,34 @@ This mod uses the full ISO-8859-1 character set (see https://en.wikipedia.org/wi
* 153-156: explosion/splat * 153-156: explosion/splat
* 157-159: smileys * 157-159: smileys
The panels also respond to these control messages: If a string is prefixed with character code 255, it is treated as UTF-8 and passed through a simple translation function. Only characters with codes greater than 159 are altered; normal ASCII text, color codes, control codes, and the above symbols are passed through unchanged. Note that in this mode, a character code over 159 is treated as the first byte of a two-byte symbol.
The panels also respond to these control messages:
the keywords "off", "colon" and "period" translate to a blank space, ":", and ".", respectively (they're leftover from the nixie tubes fork, but might be useful anyway)
* the keywords "off", "colon" and "period" translate to a blank space, ":", and ".", respectively (they're leftover from the nixie tubes fork, but might be useful anyway)
* "del" is mapped to character #127, a square with an X in it. * "del" is mapped to character #127, a square with an X in it.
* "allon" is mapped to character #144, the full/all-on block graphic. * "allon" is mapped to character #144, the full/all-on block graphic.
* "cursor" or character code 31 will display a short, thick, flashing line at the bottom of the panel. * "cursor" or character code 31 will display a short, thick, flashing line at the bottom of the panel.
* "off_multi" turns all panels in a lineup off * "off_multi" turns all panels in a lineup or wall off - essentially a "clear screen" command.
* "allon_multi" turns on all LEDs of all panels in a lineup. * "allon_multi" turns on all LEDs of all panels in a lineup/wall (by filling them with char #144).
A byte value of 0 to 27 will change colors (i.e. string.char(0 to 27) ). Color values 0 to 11 are: A byte value of 0 to 27 in a string 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) 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 12 to 23 are the same as 0 to 11, but lower brightness.
Colors 24 - 27 are white, light grey, medium grey, and dim grey. Colors 24 - 27 are white, light grey, medium grey, and dim grey (or think of them as full bright white, a bit less bright, medium brightness, and dim white).
The left-most/"master" panel will remember the last color used, and defaults to red. The last color that was used is stored in the left-most/upper-left "master" panel's metadata, and defaults to red. It should persist across reboots.
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. A byte value of 28 in a string will act as a line feed (I would have used 10, but that's a color code :-P )
A byte value of 29 in a string 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 onward with normal line wrapping, colors and so forth. Note that any string that does NOT contain cursor positioning commands will automatically start printing at the upper-left.
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. All panels emit a small amount of light when displaying something.

View File

@ -1,5 +1,5 @@
default default
digilines digilines
mesecons_luacontroller mesecons_luacontroller
mesecons_microcontroller mesecons_microcontroller?
mesecons_lamp mesecons_lamp?

View File

@ -24,6 +24,35 @@ local on_digiline_receive_std = function(pos, node, channel, msg)
end end
end end
-- convert Lua's idea of a UTF-8 char to ISO-8859-1
-- first char is non-break space, 0xA0
local iso_chars=" ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
local get_iso = function(c)
local hb = string.byte(c,1) or 0
local lb = string.byte(c,2) or 0
local dec = lb+hb*256
local char = dec - 49664
if dec > 49855 then char = dec - 49856 end
return char
end
local make_iso = function(s)
local i = 1
local s2 = ""
while i <= string.len(s) do
if string.byte(s,i) > 159 then
s2 = s2..string.char(get_iso(string.sub(s, i, i+1)))
i = i + 2
else
s2 = s2..string.sub(s, i, i)
i = i + 1
end
end
return s2
end
-- the nodes: -- the nodes:
local fdir_to_right = { local fdir_to_right = {
@ -42,43 +71,71 @@ local cbox = {
wall_side = { -8/16, -8/16, -8/16, -7/16, 8/16, 8/16 } 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) local display_string = function(pos, channel, string)
string = string.sub(string, 1, 1024)
if string == "off_multi" then if string == "off_multi" then
string = "" string = string.rep(" ", 1024)
elseif string == "allon_multi" then elseif string == "allon_multi" then
string = allon string = string.rep(string.char(144), 1024)
elseif string.sub(string,1,1) == string.char(255) then -- treat it as incoming UTF-8
string = make_iso(string.sub(string, 2, 1024))
end end
local padded_string = string.sub(string..padding, 1, 64)
local master_fdir = minetest.get_node(pos).param2 % 8 local master_fdir = minetest.get_node(pos).param2 % 8
local master_meta = minetest.get_meta(pos) local master_meta = minetest.get_meta(pos)
local last_color = master_meta:get_int("last_color") local last_color = master_meta:get_int("last_color")
local pos2 = pos local pos2 = table.copy(pos)
if not last_color or last_color < 0 or last_color > 27 then if not last_color or last_color < 0 or last_color > 27 then
last_color = 0 last_color = 0
master_meta:set_int("last_color", 0) master_meta:set_int("last_color", 0)
end 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 node = minetest.get_node(pos2)
local fdir = node.param2 % 8 local fdir = node.param2 % 8
local meta = minetest.get_meta(pos2) local meta = minetest.get_meta(pos2)
local setchan = meta:get_string("channel") local setchan = nil
if not string.match(node.name, "led_marquee:char_") or (setchan ~= nil and setchan ~= "" and setchan ~= channel) then break end if meta then setchan = meta:get_string("channel") end
local asc = string.byte(padded_string, i, i) local asc = string.byte(string, i, i)
if master_fdir == fdir and asc > 30 and asc < 256 then 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)}) 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.x = pos2.x + fdir_to_right[fdir+1][1]
pos2.z = pos2.z + fdir_to_right[fdir+1][2] pos2.z = pos2.z + fdir_to_right[fdir+1][2]
i = i + 1
wrapped = nil
elseif asc < 28 then elseif asc < 28 then
last_color = asc last_color = asc
master_meta:set_int("last_color", asc) master_meta:set_int("last_color", asc)
i = i + 1
wrapped = nil
end end
end end
end end

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