Intro
Hello everyone! Almost a year ago I released MonAPI which was an API that allowed you to make small sections within monitors that acted more or less like a regular monitor object. I had originally made this API for a project I was working on and decided to polish it up and release it. It worked but the code wasn't very pretty and it was missing some features (scroll, setCursorBlink). I had plans to implement these features but one thing I really wanted to see in the API was support for multiple monitors. Anyway, 1.6 was released and it came with a window API that basically did what my API did but it was a lot more efficient, feature-complete and better coded in general. It however did not have support for multiple monitors. Seeing this, it motivated me to work on my API again, however I wanted to just make a new API that did multiple monitors and nothing else. So that is why I am releasing multiMon.
This functions creates a virtual monitor (that is fully compatible with the peripheral API and emits monitor_touch events) out of multiple monitor objects stitched together. It accepts the following arguments:
name Name of the virtual monitor.
monitors A table in format: { { object [, ...] } [, ...] } containing the monitor objects to be stitched.
wide Optional (default: determined by 'monitors' argument). Amount of monitor objects stacked horizontally.
tall Optional (default: determined by 'monitors' argument). Amount of monitor objects stacked vertically.
width Optional (default: the width of the first object in 'monitors' argument). Width of each monitor object.
height Optional (default: the height of the first object in 'monitors' argument). Height of each monitor object.
This function returns a handle to the virtual monitor created. Same as calling peripheral.wrap(name).
Side notes:
1. All monitors should be of the width and height and the monitors stitched together should form a rectangle.
2. You must load the API [os.loadAPI("multiMon")] before wrapping to the actual monitors otherwise touch events may not work.
3. This API is meant to be used with monitors however it should be compatible with terminal and window objects.
Examples Setup:
Spoiler
Yeah, that's right 9 full size monitors. Here is what the back looks like:
Simple example:
Spoiler
--# Load the API
os.loadAPI('/multiMon')
--# Create the monitors object (the monitors are arranged in the world the same way you see them in the table below).
local monitorSetup = {
{peripheral.wrap('monitor_22'), peripheral.wrap('monitor_23'), peripheral.wrap('monitor_24')},
{peripheral.wrap('monitor_25'), peripheral.wrap('monitor_26'), peripheral.wrap('monitor_27')},
{peripheral.wrap('monitor_19'), peripheral.wrap('monitor_20'), peripheral.wrap('monitor_21')},
}
--# Create the virtual monitor (will also return the handle).
local disp = multiMon.create('myMonitor', monitorSetup)
--# Showcasing some basic functions.
disp.setTextScale(0.5)
if disp.isColour() then
disp.setTextColour(colours.white)
disp.setBackgroundColour(colours.black)
end
disp.setCursorBlink(false)
disp.clear()
disp.setCursorPos(1, 1)
local width, height = disp.getSize()
--# Writes random characters onto the screen.
for y = 1, height do
disp.setCursorPos(1, y)
disp.write(string.rep(string.char(math.random(32, 126)), width))
end
Here is what it looks like on the monitor:
Here it is with 0.5 text scale instead of 5:
Closer up:
Running paint (on the same setup):
Spoiler
--# Load the API
os.loadAPI('/multiMon')
--# Create the monitors object (the monitors are arranged in the world the same way you see them in the table below).
local monitorSetup = {
{peripheral.wrap('monitor_22'), peripheral.wrap('monitor_23'), peripheral.wrap('monitor_24')},
{peripheral.wrap('monitor_25'), peripheral.wrap('monitor_26'), peripheral.wrap('monitor_27')},
{peripheral.wrap('monitor_19'), peripheral.wrap('monitor_20'), peripheral.wrap('monitor_21')},
}
--# Create the virtual monitor (will also return the handle).
local disp = multiMon.create('myMonitor', monitorSetup)
--# Showcasing some basic functions.
disp.setTextScale(0.5)
if disp.isColour() then
disp.setTextColour(colours.white)
disp.setBackgroundColour(colours.black)
end
disp.setCursorBlink(false)
disp.clear()
disp.setCursorPos(1, 1)
local width, height = disp.getSize()
--# Some setup is needed for paint.
parallel.waitForAny(
function()
--# Since paint is meant to work only on the terminal, we need to catch all touch events and turn them into mouse_click events.
--# This happens in the background while paint is running.
while true do
local ev = {os.pullEvent('monitor_touch')}
if ev[2] == 'myMonitor' then
os.queueEvent('mouse_click', 1, ev[3], ev[4])
end
end
end,
function()
--# Since paint uses 'term' internally, we need to set 'disp' to act as 'term'.
term.redirect(disp)
--# Run the program with 'image' as the argument.
shell.run('/rom/programs/advanced/paint', 'image')
end
)
Empty canvas:
After some random brush strokes:
Playing worm (on the same setup):
Spoiler
--# Load the API
os.loadAPI('/multiMon')
--# Create the monitors object (the monitors are arranged in the world the same way you see them in the table below).
local monitorSetup = {
{peripheral.wrap('monitor_22'), peripheral.wrap('monitor_23'), peripheral.wrap('monitor_24')},
{peripheral.wrap('monitor_25'), peripheral.wrap('monitor_26'), peripheral.wrap('monitor_27')},
{peripheral.wrap('monitor_19'), peripheral.wrap('monitor_20'), peripheral.wrap('monitor_21')},
}
--# Create the virtual monitor (will also return the handle).
local disp = multiMon.create('myMonitor', monitorSetup)
--# Showcasing some basic functions.
disp.setTextScale(2)
if disp.isColour() then
disp.setTextColour(colours.white)
disp.setBackgroundColour(colours.black)
end
disp.setCursorBlink(false)
disp.clear()
disp.setCursorPos(1, 1)
local width, height = disp.getSize()
--# Since worm uses 'term' internally, we need to set 'disp' to act as 'term'.
term.redirect(disp)
--# Run the program.
shell.run('/rom/programs/fun/worm')
WOW, I actually did something really similar to this (it's on Grim's server), but it had to be rewritten because of scrolling. I even chose the same name for my program, but my version would have had a lot more features than yours have, huh, maybe I'll make it one day...
But nice job doing this, glad I'm not the only one who has made something like this .
Haha. That's what I accutly did. I tried making a .. about 460*380 Display.
Though it doesn't look like a real Display, Cause CC's pixels are shaped like rectangles.
Also, I was really getting about 1- 5 FPS on Max Ram and lowest Graphic detail settings when the monitor was on. About 60- 260 FPS is ussaly what I get. (Proboly 115 The most)
But it works, anyways
WOW, I actually did something really similar to this (it's on Grim's server), but it had to be rewritten because of scrolling. I even chose the same name for my program, but my version would have had a lot more features than yours have, huh, maybe I'll make it one day...
But nice job doing this, glad I'm not the only one who has made something like this .
What a coincidence, especially the name. Any features you would like to see in this version?
WOW, I actually did something really similar to this (it's on Grim's server), but it had to be rewritten because of scrolling. I even chose the same name for my program, but my version would have had a lot more features than yours have, huh, maybe I'll make it one day...
But nice job doing this, glad I'm not the only one who has made something like this />.
What a coincidence, especially the name. Any features you would like to see in this version?
Anything you can imagine . Maybe a program with which you could redirect terminal to the monitor, auto-adjusting and centering the redirected output to the center of the giant monitor. Also, does this support non-advanced monitors? What if I would make one monitor advanced and the other one non-advanced? Would it act like an advanced or not?
Anything you can imagine . Maybe a program with which you could redirect terminal to the monitor, auto-adjusting and centering the redirected output to the center of the giant monitor. Also, does this support non-advanced monitors? What if I would make one monitor advanced and the other one non-advanced? Would it act like an advanced or not?
Those are great ideas but I would like this to be just a simple API which mimics a regular monitor object. And yes, it does support non-advanced monitors. If there is at least 1 non-advanced monitor then the virtual monitor will act like a non-advanced monitor.
This is Amazing! However, I do have some suggestions:
-Remove the name part in the create function, I don't see why it's needed and is really annoying when it error saying the monitor already exists
-Since you are already overriding all the commands, add these: disp.getTextScale, disp.getBackgroundColor, and disp.getTextColor.
-if the name isn't removed, or you use OO, an "add monitor" function could be useful. Also a way to remove an already created (virtual) monitor.
Edited by KingofGamesYami, 01 May 2014 - 11:41 PM.
This is Amazing! However, I do have some suggestions:
-Remove the name part in the create function, I don't see why it's needed and is really annoying when it error saying the monitor already exists
-Since you are already overriding all the commands, add these: disp.getTextScale, disp.getBackgroundColor, and disp.getTextColor.
-if the name isn't removed, or you use OO, an "add monitor" function could be useful. Also a way to remove an already created (virtual) monitor.
- The name specifies the virtual peripheral's name, so you can use peripheral.* functions and it's also used for monitor_touch events. (I might make the name optional and disable peripheral.* and monitor_touch events if it's not specified.)
- Good idea, will add those in the next version.
- I'm not sure what you mean by "add monitor" but I will look into adding a way to remove a virtual monitor.
- I'm not sure what you mean by "add monitor" but I will look into adding a way to remove a virtual monitor.
I meant that you could add another monitor to the virtual monitor. Say I have this setup:
M M M
M M M
and I want to make it
M M M M
M M M M
Shazz, on 03 May 2014 - 05:57 PM, said:
The name specifies the virtual peripheral's name, so you can use peripheral.* functions and it's also used for monitor_touch events. (I might make the name optional and disable peripheral.* and monitor_touch events if it's not specified.)
Yes, but in the example you have it returning a value anyway. Using OO (not saying you should) you could make the virtual monitor anything you want, and it would return a pointer to it.
Edited by KingofGamesYami, 04 May 2014 - 05:34 PM.
I meant that you could add another monitor to the virtual monitor. Say I have this setup:
M M M
M M M
and I want to make it
M M M M
M M M M
I'll look into that.
KingofGamesYami, on 04 May 2014 - 05:12 PM, said:
Yes, but in the example you have it returning a value anyway. Using OO (not saying you should) you could make the virtual monitor anything you want, and it would return a pointer to it.
The whole point of this API is to create a virtual monitor that acts the same way as a real monitor attached as a peripheral would. The reasoning behind this is so that programs that use the peripheral.* will work properly. Also, the name is used for monitor_touch events, since a monitor_touch event needs to emit the name of the monitor along with the x & y. The fact that the create function returns the handle is just for convenience; so you wouldn't have to do:
create('mMon', ...)
local myMon = peripheral.wrap('mMon')
instead you could just do this:
local myMon = create('mMon', ...)
In fact, if you look at the API code, you will see:
The whole point of this API is to create a virtual monitor that acts the same way as a real monitor attached as a peripheral would. The reasoning behind this is so that programs that use the peripheral.* will work properly. Also, the name is used for monitor_touch events, since a monitor_touch event needs to emit the name of the monitor along with the x & y. The fact that the create function returns the handle is just for convenience; so you wouldn't have to do:
create('mMon', ...)
local myMon = peripheral.wrap('mMon')
instead you could just do this:
local myMon = create('mMon', ...)
In fact, if you look at the API code, you will see:
return peripheral.wrap(name)
I get that you are making a virtual monitor, I am saying you should create your own name inside the api, instead of having the programmer name it themselves.
The whole point of this API is to create a virtual monitor that acts the same way as a real monitor attached as a peripheral would. The reasoning behind this is so that programs that use the peripheral.* will work properly. Also, the name is used for monitor_touch events, since a monitor_touch event needs to emit the name of the monitor along with the x & y. The fact that the create function returns the handle is just for convenience; so you wouldn't have to do:
create('mMon', ...)
local myMon = peripheral.wrap('mMon')
instead you could just do this:
local myMon = create('mMon', ...)
In fact, if you look at the API code, you will see:
return peripheral.wrap(name)
I get that you are making a virtual monitor, I am saying you should create your own name inside the api, instead of having the programmer name it themselves.
To be honest, I believe it would be better the way it is now as it allows use of other overriden peripheral functions - find, getNames, etc.
-snip-
To be honest, I believe it would be better the way it is now as it allows use of other overriden peripheral functions - find, getNames, etc.
I don't mean change anything fundamental, all I was thinking was generating it's own name. Instead of you using create(name, monitors), use create(monitors) which returns name. You could use disp = peripheral.wrap(create(monitors)) to get the wrapped peripheral. It was a way to eliminate this error:
peripheral already exists
but this would be irrelevant if a way to delete a disp was added.
-snip-
To be honest, I believe it would be better the way it is now as it allows use of other overriden peripheral functions - find, getNames, etc.
I don't mean change anything fundamental, all I was thinking was generating it's own name. Instead of you using create(name, monitors), use create(monitors) which returns name. You could use disp = peripheral.wrap(create(monitors)) to get the wrapped peripheral. It was a way to eliminate this error:
peripheral already exists
but this would be irrelevant if a way to delete a disp was added.
In that case, why not make the argument optional? If it's missing or nil, a name is generated, otherwise it uses the passed argument.
You could do that, but I was thinking more of if you loop a section of code, and it happens to create the monitor new each time or something similar.
That would still work fine. Just leave out the argument and it automatically generates the name for you. And if you want to set a name yourself, add the extra argument.