Each frame needs to be 31x31px, only the first 96 colors from the palette will be used, frames can have transparent backgrounds, there are 2 different types of alpha modes.
It runs pretty fast without making the game stutter thanks to the way each frame line is drawn (technicalities at the bottom).
NOTES:
- As of the writing of this readme, the only software existing that can stream a visual to uscript is the one contained in this project, till someone will make a different one, and it is written in Python, so if you want to run this you will need to install Python and follow the instructions.
- Replication has not been taken in account for this project, it has been tested in Single Player only.
Configurable properties (Editor):
<Info -> VSPDisplay>
bDebug - Enable debug (just verbosity).
serverHost - The IP used by the streamer software.
serverPort - The port used by the streamer software.
socketPort - The port the display will receive the stream on.
scrTex - The ScriptedTexture the display will draw on.
bgTex - A background texture that replaces scrTex's texture. (Optional).
posRow - The row index of this display in a grid of displays.
posCol - The column index of this display in a grid of displays.
pixRows - The display's height resolution.
pixCols - The display's width resolution.
palFont - The font of which characters will be drawn on scrTex. (See "palette font" below).
palTex - A texture that uses the same palette of palFont's texture.
displayName - An ID used for debug purposes. (Optional).
frameStr - The last received frame. Configurable to allow a placeholder frame. (Optional).
The content of the zip file
- The main .u files.
- An example map with 4 displays arranged in a 2x2 grid, thus bringing the resolution to 62x62px.
- A Python program to split an image or a video in 4 and send it to the 4 displays.
- Some image and video examples.
- An example "palette font" (explained at the bottom), which in turns means an example palette (a color one).
- A "palette font" generator that generates a "palette font" having a "palette texture".
- An example "palette texture" (A dummy texture useful only for extracting its palette) as a .u file.
- A readme with instructions.
Video demos
Transparent background:
Background replaced:
Webcam feed:
Background replaced:
Webcam feed:
(This tutorial is for Windows, it doesn't differ that much for Linux)
After placing the files that are within the EXAMPLES folder in the respective folders in the game's path do the following:
1. Install Python if you don't have it yet;
2. Open a command prompt in the SOFTWARE/visual_streamer_1 path;
3. Run the command 'python -m venv venv', this will create a Python virtual environment so we can run the software in it;
4. Run the command 'venv/Scripts/activate', this will enter the virtual environment.
5. Run the command 'pip install -r requirements.txt' to install the required libraries written in requirements.txt;
6. Start the map;
7. Run the command 'python main.py';
8. It'll ask you to input the media path you want to stream, you can find some examples in the 'media_examples' folder;
9. When it'll ask for the "Font texture path" input the path 'palette_font_examples/palette_font.bmp' (It's a color palette);
10. Grab some popcorns and enjoy your theater while being in the map.
How does it work? / Technicalities:
Text. That's the key to draw a frame faster than doing it manually in uscript.
It uses ScriptedTexture to draw text on a surface, just like those scrolling messages on DM-Morpheus, this one draws a special kind of text.
The text it uses is made of 1x1px characters, each with a different color, arranged in the same order of the colors in a palette (the one you choose).
This palette is then used by the ScriptedTexture to paint the characters correctly, it must also be used by the software that will stream the frames to uscript (you can find a software in Python that does it for you in the zip).
Wait... but why does it run that fast? - your inner programmer may be wondering - Presto detto!
Normally one would iterate through each pixel by using two "for"s and drawing each pixel separately, that is indeed pretty slow, for a 31x31 image this means it would perform 961 iterations each frame, and that's a lot!
But when we draw a line of text using drawText() the iterations performed to draw each character separately are done entirely on native, at this point all we have to do is using a single "for" to iterate for each line of text in uscript, thus cutting down the iterations to 31, and that's a lot... less!
It could dynamically load the font to let an external software create it at run-time, but ain't nobody got time for that.