10 posts
Posted 19 December 2012 - 09:10 AM
Hi,
I'm trying to make a simple OS and I would like to have a clock at the top right of the screen, however I can't work out how to keep the time updating while the OS does other things.
I've seen it done in other OSes but I can't work out how they do it.
Please help!
Thanks,
_Black_Viper_
92 posts
Posted 19 December 2012 - 09:17 AM
You would use the coroutine API. Sadly, I don't have much knowledge in this myself.
1054 posts
Posted 19 December 2012 - 09:21 AM
This is a bad solution, but the only one I can give you without seeing your current code:
local bRunning = true
local function OS_Stuff()
while bRunning do
-- OS Stuff : just make bRunning false to end everything
-- make sure to make it yield here
end
end
local function clock()
while bRunning do
local time = textutils.formatTime(os.time(),true)
local w,h = term.getSize()
term.setCursorPos(1,w-#time)
term.write(time)
sleep(1)
term.setCursorPos(1,w-#time)
term.write( string.rep(" ", #time) )
end
end
parallel.waitForAny(OS_Stuff, clock)
10 posts
Posted 19 December 2012 - 09:32 AM
This is a bad solution, but the only one I can give you without seeing your current code:
local bRunning = true
local function OS_Stuff()
while bRunning do
-- OS Stuff : just make bRunning false to end everything
-- make sure to make it yield here
end
end
local function clock()
while bRunning do
local time = textutils.formatTime(os.time(),true)
local w,h = term.getSize()
term.setCursorPos(1,h-#time)
term.write(time)
sleep(1)
term.setCursorPos(1,h-#time)
term.write( string.rep(" ", #time) )
end
end
parallel.waitForAny(OS_Stuff, clock)
This is the code I'd like to put a clock on first:
Spoiler
function drawTiles(fgColour,fgTextColour,bgColour)
tilePosX = 2 + tileUserPosX
tilePosY = 2
drawBackground(bgColour)
for i = 1,#programs do
for y = 0,4 do
for x = 0,6 do
paintutils.drawPixel(tilePosX + x,tilePosY + y,fgColour)
end
end
term.setTextColor(fgTextColour)
if tilePosX < 46 then
term.setCursorPos(tilePosX + math.ceil(3 - (#programs[i] / 2)),tilePosY + 2)
write(programs[i])
end
if tilePosY > 8 then
tilePosY = 2
tilePosX = tilePosX + 9
else
tilePosY = tilePosY + 6
end
end
end
function drawSidebar(fgColour,bgColour,textColour)
for y = 1,19 do
for x = 43,51 do
paintutils.drawPixel(x,y,fgColour)
end
paintutils.drawPixel(42,y,bgColour)
end
term.setTextColour(textColour)
term.setBackgroundColour(fgColour)
term.setCursorPos(44,4)
write("Search")
term.setCursorPos(44,10)
write("Options")
term.setCursorPos(44,16)
write("Sleep")
end
term.setTextColor(1)
programs = fs.list("programs")
table.insert(programs,"Options")
if admin == "true" then
table.insert(programs,"Setup")
end
tileUserPosX = 0
tileSelected = 0
while tileSelected == 0 do
drawTiles(foregroundColour,foregroundTextColour,backgroundColour)
drawSidebar(foregroundColour,backgroundColour,foregroundTextColour)
a,b,c,d = os.pullEvent()
if a == "mouse_scroll" and b == 1 and tileUserPosX < -1 then
tileUserPosX = tileUserPosX + 2
elseif a == "mouse_scroll" and b == 1 and tileUserPosX < 0 then
tileUserPosX = tileUserPosX + 1
elseif a == "mouse_scroll" and b == -1 and tileUserPosX > 0 - (math.ceil(#programs / 3) * 9 - 43) then
tileUserPosX = tileUserPosX - 2
elseif a == "mouse_scroll" and b == -1 and tileUserPosX > 0 - (math.ceil(#programs / 3) * 9 - 42) then
tileUserPosX = tileUserPosX - 1
elseif a == "mouse_click" and b == 1 and c < 42 then
tileSelectedX = math.ceil((c - tileUserPosX) / 9) * 3
tileSelectedY = math.ceil(d / 6)
tileSelected = tileSelectedX + tileSelectedY - 3
if programs[tileSelected] == "Options" then
shell.run("system/options")
elseif programs[tileSelected] == "Setup" then
shell.run("system/setup")
elseif tileSelectedY < 4 and programs[tileSelected] ~= nil then
shell.run("programs/"..programs[tileSelected])
else
tileSelected = 0
end
end
end
It shows every program in the "programs/" directory as a clickable tile.
The variables foregroundColour, foregroundTextColour, backgroundColour and backgroundTextColour are from another program which is run before this and the bar on the right is currently WIP.
2088 posts
Location
South Africa
Posted 19 December 2012 - 09:45 AM
Well just add
parallel.waitForAny(yourMainFunction, clock)
at the bottom and it should work.
PS Orwell: what exactly does this part of your code do:
term.setCursorPos(1,h-#time)
term.write( string.rep(" ", #time) )
Also did you not mean to subract #time from w? Like so to get it at the bottom right:
local function clock()
while bRunning do
local time = textutils.formatTime(os.time(),true)
local w,h = term.getSize()
term.setCursorPos(w-#time+1,h)
term.write(time)
sleep(1)
end
end
1054 posts
Posted 19 December 2012 - 12:18 PM
Well just add
parallel.waitForAny(yourMainFunction, clock)
at the bottom and it should work.
PS Orwell: what exactly does this part of your code do:
term.setCursorPos(1,h-#time)
term.write( string.rep(" ", #time) )
Also did you not mean to subract #time from w? Like so to get it at the bottom right:
local function clock()
while bRunning do
local time = textutils.formatTime(os.time(),true)
local w,h = term.getSize()
term.setCursorPos(w-#time+1,h)
term.write(time)
sleep(1)
end
end
You are right, I totally derped out. :P/> I edited my post with the correction. I put those 2 lines there to clear the clock in case the time gets a digit shorter. Otherwise the digit will just stay there. Of course, you could also prepend shorter times with one space, what ever you want. I also don't clear the whole screen or line because it could interfere with the main loop.
2088 posts
Location
South Africa
Posted 19 December 2012 - 12:32 PM
Ah I see. Well alternatively you could use term.clearLine()
1054 posts
Posted 19 December 2012 - 03:44 PM
Ah I see. Well alternatively you could use term.clearLine()
That could interfere with the main loop printing on the first line.
249 posts
Location
In the universe
Posted 19 December 2012 - 04:30 PM
I don't know if it works, but using parallel with os.pullEvent() will not run the other code until an event has been triggered. I am right?
1054 posts
Posted 19 December 2012 - 04:34 PM
I don't know if it works, but using parallel with os.pullEvent() will not run the other code until an event has been triggered. I am right?
I'm quite sure it will. It keeps yielding until there is an event to be pulled.
249 posts
Location
In the universe
Posted 19 December 2012 - 04:38 PM
I don't know if it works, but using parallel with os.pullEvent() will not run the other code until an event has been triggered. I am right?
I'm quite sure it will. It keeps yielding until there is an event to be pulled.
I will try it soon, it didn't worked for me a time I use it (the first and last time I used it)
1054 posts
Posted 19 December 2012 - 04:41 PM
I don't know if it works, but using parallel with os.pullEvent() will not run the other code until an event has been triggered. I am right?
I'm quite sure it will. It keeps yielding until there is an event to be pulled.
I will try it soon, it didn't worked for me a time I use it (the first and last time I used it)
If this is indeed the case, then you can solve it by doing "coroutine.yield()" yourself (if this is appropiate in the context) or you could do "os.startTimer(interval)" to trigger the os.pullEvent after a certain interval when you're using it in a loop.
249 posts
Location
In the universe
Posted 19 December 2012 - 04:43 PM
I don't know if it works, but using parallel with os.pullEvent() will not run the other code until an event has been triggered. I am right?
I'm quite sure it will. It keeps yielding until there is an event to be pulled.
I will try it soon, it didn't worked for me a time I use it (the first and last time I used it)
If this is indeed the case, then you can solve it by doing "coroutine.yield()" yourself (if this is appropiate in the context) or you could do "os.startTimer(interval)" to trigger the os.pullEvent after a certain interval when you're using it in a loop.
The most effective way is the os.startTimer() to run an os.pullEvet, except you run another type of event and then yield the function
1054 posts
Posted 19 December 2012 - 05:17 PM
* snip *
The most effective way is the os.startTimer() to run an os.pullEvet, except you run another type of event and then yield the function
Isn't it easier like this?
local interval = 1
while true do
os.startTimer(interval)
local e,p1,p2,p3 = os.pullEvent()
if e == "key" then
-- ...
elseif e == "rednet_message" then
-- ...
end
end
That will yield every second and still handle all events properly.
997 posts
Location
Wellington, New Zealand
Posted 19 December 2012 - 09:30 PM
* snip *
The most effective way is the os.startTimer() to run an os.pullEvet, except you run another type of event and then yield the function
Isn't it easier like this?
local interval = 1
while true do
os.startTimer(interval)
local e,p1,p2,p3 = os.pullEvent()
if e == "key" then
-- ...
elseif e == "rednet_message" then
-- ...
end
end
That will yield every second and still handle all events properly.
You don't need to do anything special to yield, besides making sure you call os.pullEvent at all.
10 posts
Posted 19 December 2012 - 10:04 PM
Using the parallel api is working, except for one thing. The clock disappears while the program is scrolling. Any ideas?
Edit: I found the problem. Every time I scrolled, it painted over the clock until the clock was drawn again. Simple solution: don't paint over the clock.
Well just add
parallel.waitForAny(yourMainFunction, clock)
at the bottom and it should work.
Thanks so much :D/>
I didn't realise there was a parallel api, there's so much more I can do now!
2088 posts
Location
South Africa
Posted 20 December 2012 - 01:09 AM
Ah I see. Well alternatively you could use term.clearLine()
That could interfere with the main loop printing on the first line.
Huh? You can put it just before it prints the time?
1054 posts
Posted 20 December 2012 - 02:22 AM
Ah I see. Well alternatively you could use term.clearLine()
That could interfere with the main loop printing on the first line.
Huh? You can put it just before it prints the time?
If the os loop prints something on the first line and doesn't reprint it between yields, then term.clearLine() could remove the line that the os loop printed.