Edited by TheJebForge, 22 January 2015 - 02:13 PM.
[Solved]Need help with multishell script. {READ THIS, NEED HELP}
#1
Posted 17 January 2015 - 05:43 PM
#2
Posted 17 January 2015 - 05:51 PM
-- Setup process switching
local parentTerm = term.current()
local w,h = parentTerm.getSize()
local tProcesses = {}
local nCurrentProcess = nil
local nRunningProcess = nil
local bShowMenu = false
local bWindowsResized = false
local function selectProcess( n )
if nCurrentProcess ~= n then
if nCurrentProcess then
local tOldProcess = tProcesses[ nCurrentProcess ]
tOldProcess.window.setVisible( false )
end
nCurrentProcess = n
if nCurrentProcess then
local tNewProcess = tProcesses[ nCurrentProcess ]
tNewProcess.window.setVisible( true )
tNewProcess.bInteracted = true
end
end
end
local function setProcessTitle( n, sTitle )
tProcesses[ n ].sTitle = sTitle
end
local function resumeProcess( nProcess, sEvent, ... )
local tProcess = tProcesses[ nProcess ]
local sFilter = tProcess.sFilter
if sFilter == nil or sFilter == sEvent or sEvent == "terminate" then
local nPreviousProcess = nRunningProcess
nRunningProcess = nProcess
term.redirect( tProcess.terminal )
local ok, result = coroutine.resume( tProcess.co, sEvent, ... )
tProcess.terminal = term.current()
if ok then
tProcess.sFilter = result
else
printError( result )
end
nRunningProcess = nPreviousProcess
end
end
local function launchProcess( tProgramEnv, sProgramPath, ... )
local tProgramArgs = { ... }
local nProcess = #tProcesses + 1
local tProcess = {}
tProcess.sTitle = fs.getName( sProgramPath )
if bShowMenu then
tProcess.window = window.create( parentTerm, 1, 2, w, h-1, false )
else
tProcess.window = window.create( parentTerm, 1, 1, w, h, false )
end
tProcess.co = coroutine.create( function()
os.run( tProgramEnv, sProgramPath, unpack( tProgramArgs ) )
if not tProcess.bInteracted then
term.setCursorBlink( false )
print( "Press any key to continue" )
os.pullEvent( "char" )
end
end )
tProcess.sFilter = nil
tProcess.terminal = tProcess.window
tProcess.bInteracted = false
tProcesses[ nProcess ] = tProcess
resumeProcess( nProcess )
return nProcess
end
local function cullProcess( nProcess )
local tProcess = tProcesses[ nProcess ]
if coroutine.status( tProcess.co ) == "dead" then
if nCurrentProcess == nProcess then
selectProcess( nil )
end
table.remove( tProcesses, nProcess )
if nCurrentProcess == nil then
if nProcess > 1 then
selectProcess( nProcess - 1 )
elseif #tProcesses > 0 then
selectProcess( 1 )
end
end
return true
end
return false
end
local function cullProcesses()
local culled = false
for n=#tProcesses,1,-1 do
culled = culled or cullProcess( n )
end
return culled
end
-- Setup the main menu
local menuMainTextColor, menuMainBgColor, menuOtherTextColor, menuOtherBgColor
if parentTerm.isColor() then
menuMainTextColor, menuMainBgColor = colors.yellow, colors.black
menuOtherTextColor, menuOtherBgColor = colors.black, colors.gray
else
menuMainTextColor, menuMainBgColor = colors.white, colors.black
menuOtherTextColor, menuOtherBgColor = colors.black, colors.white
end
local function redrawMenu()
if bShowMenu then
local nat = term.native()
nat.setBackgroundColor(128)
nat.setTextColor(256)
nat.setCursorPos(1,1)
nat.clearLine()
nat.write("NxOS")
if #tProcesses > 1 then
nat.setCursorPos(50,1)
nat.write("X")
end
end
end
local function stopProcess(nProcess)
local tProcess = tProcesses[n]
if nCurrentProcess > nProcess then
table.remove( tProcesses, nProcess )
nCurrentProcess = nCurrentProcess - 1
local tNewProcess = tProcesses[ nCurrentProcess ]
tNewProcess.window.setVisible( true )
tNewProcess.bInteracted = true
else
table.remove( tProcesses, nProcess )
if nProcess > 1 then
nCurrentProcess = nProcess - 1
local tNewProcess = tProcesses[ nCurrentProcess ]
tNewProcess.window.setVisible( true )
tNewProcess.bInteracted = true
redrawMenu()
elseif #tProcesses > 0 then
nCurrentProcess = 1
local tNewProcess = tProcesses[ nCurrentProcess ]
tNewProcess.window.setVisible( true )
tNewProcess.bInteracted = true
redrawMenu()
end
end
sleep(0.01)
end
local function resizeWindows()
local windowY, windowHeight
if bShowMenu then
windowY = 2
windowHeight = h-1
else
windowY = 1
windowHeight = h
end
for n=1,#tProcesses do
local tProcess = tProcesses[n]
local window = tProcess.window
local x,y = tProcess.window.getCursorPos()
if y > windowHeight then
tProcess.window.scroll( y - windowHeight )
tProcess.window.setCursorPos( x, windowHeight )
end
tProcess.window.reposition( 1, windowY, w, windowHeight )
end
bWindowsResized = true
end
local function setMenuVisible( bVis )
if bShowMenu ~= bVis then
bShowMenu = bVis
resizeWindows()
redrawMenu()
end
end
local multishell = {}
function multishell.getFocus()
return nCurrentProcess
end
function multishell.setFocus( n )
if n >= 1 and n <= #tProcesses then
selectProcess( n )
redrawMenu()
return true
end
return false
end
function multishell.getTitle( n )
if n >= 1 and n <= #tProcesses then
return tProcesses[n].sTitle
end
return nil
end
function multishell.setTitle( n, sTitle )
if n >= 1 and n <= #tProcesses then
setProcessTitle( n, sTitle )
redrawMenu()
end
end
function multishell.stopProcess(n)
if #tProcesses > 1 then
stopProcess(n)
else
err("Only 1 process there! (Press any button to con.)")
os.pullEvent("key")
end
end
function multishell.getCurrent()
return nRunningProcess
end
function multishell.launch( tProgramEnv, sProgramPath, ... )
if #tProcesses < 16 then
local previousTerm = term.current()
setMenuVisible( (#tProcesses + 1) >= 2 )
local nResult = launchProcess( tProgramEnv, sProgramPath, ... )
redrawMenu()
term.redirect( previousTerm )
return nResult
else
err("Too many processes ran!")
print("Press Anu Button")
os.pullEvent("key")
end
end
function multishell.getCount()
return #tProcesses
end
function multishell.setMenuVisible( bol )
setMenuVisible( bol )
end
-- Begin
setMenuVisible( false )
redrawMenu()
selectProcess( launchProcess( {
["shell"] = shell,
["multishell"] = multishell,
}, "/rom/programs/shell" ) )
redrawMenu()
-- Run processes
while #tProcesses > 0 do
-- Get the event
local tEventData = { os.pullEventRaw() }
local sEvent = tEventData[1]
if sEvent == "term_resize" then
-- Resize event
w,h = parentTerm.getSize()
resizeWindows()
redrawMenu()
elseif sEvent == "char" or sEvent == "key" or sEvent == "paste" or sEvent == "terminate" then
-- Keyboard event
-- Passthrough to current process
resumeProcess( nCurrentProcess, unpack( tEventData ) )
if cullProcess( nCurrentProcess ) then
setMenuVisible( #tProcesses >= 1 )
redrawMenu()
end
elseif sEvent == "mouse_click" then
-- Click event
local button, x, y = tEventData[2], tEventData[3], tEventData[4]
if x >= 1 and x <= 5 and y == 1 and bShowMenu and not (tProcesses[#tProcesses].sTitle == "Manager.lua") then
selectProcess( multishell.launch({
["shell"] = shell,
["multishell"] = multishell,
},"/NxOS/Core/Manager.lua"))
end
if x == 50 and y == 1 and bShowMenu and #tProcesses > 1 then
stopProcess(nCurrentProcess)
end
-- Passthrough to current process
resumeProcess( nCurrentProcess, sEvent, button, x, (bShowMenu and y-1) or y )
if cullProcess( nCurrentProcess ) then
setMenuVisible( #tProcesses >= 1 )
redrawMenu()
end
elseif sEvent == "mouse_drag" or sEvent == "mouse_scroll" then
-- Other mouse event
local p1, x, y = tEventData[2], tEventData[3], tEventData[4]
if not (bShowMenu and y == 1) then
-- Passthrough to current process
resumeProcess( nCurrentProcess, sEvent, p1, x, (bShowMenu and y-1) or y )
if cullProcess( nCurrentProcess ) then
setMenuVisible( #tProcesses >= 1 )
redrawMenu()
end
end
else
-- Other event
-- Passthrough to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n=1,nLimit do
resumeProcess( n, unpack( tEventData ) )
end
if cullProcesses() then
setMenuVisible( #tProcesses >= 1 )
redrawMenu()
end
end
if bWindowsResized then
-- Pass term_resize to all processes
local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event
for n=1,nLimit do
resumeProcess( n, "term_resize" )
end
bWindowsResized = false
if cullProcesses() then
setMenuVisible( #tProcesses >= 1 )
redrawMenu()
end
end
end
-- Shutdown
term.redirect( parentTerm )
Code of Manager.lua
function p(x,y,color)
paintutils.drawPixel(x,y,color)
end
function l(x,y,endx,endy,color)
paintutils.drawLine(x,y,endx,endy,color)
end
function fg(app)
shell.switchTab(shell.openTab("test"))
end
function sCP(x,y)
term.setCursorPos(x,y)
end
function cl()
term.clear()
end
function blink(bol)
term.setCursorBlink(bol)
end
function box(x,y,endx,endy,color)
for i = 1,(endx - x + 1),1 do
for j = 1,(endy - y + 1),1 do
p(x - 1 + i, y - 1 + j,color)
end
end
end
function tpr(text,x,y)
term.setCursorPos(x,y)
term.write(text)
end
function cpr(text,y)
local w,h = term.getSize()
local x = w / 2 - string.len(text) / 2
tpr(text,x,y)
end
function bg(color)
term.setBackgroundColor(color)
end
function tg(color)
term.setTextColor(color)
end
function reloadConfig()
config = {}
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","r")
local temp = fil.readLine()
local t = 0
while temp do
t = t + 1
config[t] = temp
temp = fil.readLine()
end
fil.close()
end
function modConfig(id,text)
config[id] = text
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","w")
for i = 1, #config,1 do
fil.writeLine(config[i])
end
fil.close()
end
box(1,1,51,18,1)
tg(32768)
tpr("ID",2,1)
tpr("Name",5,1)
-- Vars
pwm = 0
local function PwMenu()
box(2,14,11,17,256)
tg(32768)
tpr("ShutDown",3,15)
tpr("Reboot",4,16)
while true do
local event,b,x,y = os.pullEvent()
if event == "mouse_click" then
if x >= 2 and x <= 11 and y <= 17 and y >= 14 and b == 1 then
if y == 16 then
os.reboot()
end
if y == 15 then
os.shutdown()
end
else
break
end
end
end
end
local function refresh()
for i = 1,16, 1 do
l(2,i+1,50,i+1,1)
end
for i = 1, multishell.getCount() do
l(2,i+1,50,i+1,256)
end
if pwm == 0 then
bg(256)
tpr("Power ^",2,18)
else
bg(128)
tpr("Power v",2,18)
end
bg(256)
for i = 1, multishell.getCount(),1 do
tpr(i,2,i+1)
tpr(multishell.getTitle(i),5,i+1)
bg(128)
tg(32768)
if multishell.getTitle(i) == multishell.getTitle(multishell.getCurrent()) then
else
tpr("Sw.To",43,i+1)
end
if i > 1 then
if multishell.getCurrent() == i then
else
tpr("X",49,i+1)
end
end
bg(256)
tg(32768)
end
end
refresh()
while true do
local event,b,x,y = os.pullEvent()
if event == "mouse_click" then
if x >= 2 and x <= 13 and b == 1 then
end
if x >= 2 and x <= 8 and y == 18 and b == 1 then
pwm = 1
refresh()
PwMenu()
pwm = 0
box(1,14,20,18,1)
refresh()
end
for i = 1, multishell.getCount(),1 do
if x == 49 and y == (i + 1) and b == 1 and i > 1 then
if multishell.getCurrent() == i then
else
multishell.stopProcess(i)
sleep(0.01)
refresh()
end
end
end
if x >= 43 and x <= 47 and b == 1 then
if y == 2 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 3 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 4 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 5 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 6 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 7 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 8 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 9 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 10 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 11 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 12 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 13 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 14 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 15 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 16 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
if y == 17 then
if multishell.getCurrent() == y - 1 then
else
shell.switchTab(y - 1)
return
end
end
end
end
end
The code of custom functions
function p(x,y,color)
paintutils.drawPixel(x,y,color)
end
function l(x,y,endx,endy,color)
paintutils.drawLine(x,y,endx,endy,color)
end
function fg(app)
local dir = shell.dir() .. "/"
shell.run("cd /")
shell.run("fg "..app)
shell.run("cd "..dir)
end
function bbg(app)
local dir = shell.dir() .. "/"
shell.run("cd /")
shell.run("bg "..app)
shell.run("cd "..dir)
end
function sCP(x,y)
term.setCursorPos(x,y)
end
function cl()
term.clear()
end
function blink(bol)
term.setCursorBlink(bol)
end
function box(x,y,endx,endy,color)
for i = 1,(endx - x + 1),1 do
for j = 1,(endy - y + 1),1 do
p(x - 1 + i, y - 1 + j,color)
end
end
end
function tpr(text,x,y)
term.setCursorPos(x,y)
term.write(text)
end
function cpr(text,y)
local w,h = term.getSize()
local x = w / 2 - string.len(text) / 2
tpr(text,x,y)
end
function bg(color)
term.setBackgroundColor(color)
end
function tg(color)
term.setTextColor(color)
end
function reloadConfig()
config = {}
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","r")
local temp = fil.readLine()
local t = 0
while temp do
t = t + 1
config[t] = temp
temp = fil.readLine()
end
fil.close()
end
function modConfig(id,text)
config[id] = text
fil = fs.open("NxOS/Core/Data/UserPreferences.lua","w")
for i = 1, #config,1 do
fil.writeLine(config[i])
end
fil.close()
end
#3
Posted 17 January 2015 - 05:54 PM
TheJebForge, on 17 January 2015 - 05:43 PM, said:
About all multishell program have their applications one layer higher which means one level lower in performance.
otherwise the applications themselves need to be compatible to the specific multishell. it's because the call is "routed" one time more often than usual. it makes drawing slow. there are even benchmarks to prove this behaviour.
OMG, please spoiler them or better put a link to a gist or pastebin(cause syntax highlighting)
#4
Posted 17 January 2015 - 05:55 PM
#5
Posted 17 January 2015 - 06:00 PM
TheJebForge, on 17 January 2015 - 05:55 PM, said:
Dude, you need to tell more about your actual problem. you can't expect us to be solving your problems magically without even knowing the problem
It seems rather rude to me(maybe I'm sensitive right now), that you call to us to fix your problems.
and also, if you change to container your code, please edit your title as well.
#6
Posted 17 January 2015 - 06:02 PM
#7
Posted 17 January 2015 - 06:05 PM
TheJebForge, on 17 January 2015 - 06:02 PM, said:
#8
Posted 17 January 2015 - 06:08 PM
Edited by TheJebForge, 17 January 2015 - 06:09 PM.
#9
Posted 17 January 2015 - 06:15 PM
On computers without multishell you draw like this: terminal API (term.draw) > native terminal object
On multishell you have: terminal API > window API > native terminal
On your code you have: terminal API > window API > window API > native terminal.
Multiple layers of multishell will slow slow down things a lot, though I don't see why it would take 2 seconds (ClamShell have a buffer implemented for scrolling and there is not that much performance difference).
Edited by SquidDev, 17 January 2015 - 06:16 PM.
#10
Posted 17 January 2015 - 06:18 PM
#11
Posted 17 January 2015 - 06:18 PM
#12
Posted 17 January 2015 - 06:24 PM
But the problem hasn't gone...
Edited by TheJebForge, 17 January 2015 - 06:26 PM.
#14
Posted 17 January 2015 - 06:29 PM
#16
Posted 17 January 2015 - 06:32 PM
What are you talking about?.
Edited by TheJebForge, 17 January 2015 - 06:35 PM.
#17
Posted 17 January 2015 - 06:35 PM
#18
Posted 17 January 2015 - 06:37 PM
#19
Posted 20 January 2015 - 03:47 PM
#20
Posted 21 January 2015 - 02:39 AM
For example, this:
function l(x,y,endx,endy,color) -- l is a new function which runs the paintutils.drawLine function paintutils.drawLine(x,y,endx,endy,color) end . . . for i = 1, multishell.getCount() do l(2,i+1,50,i+1,256) -- call l, which then calls paintutils.drawLine = 2 calls end
... takes more time to execute than this:
for i = 1, multishell.getCount() do paintutils.drawLine(2,i+1,50,i+1,256) -- just call paintutils.drawLine = 1 call end
... because you are doubling the amount of function calls you're performing.
On the other hand, if you do this:
local l = paintutils.drawLine -- l and paintutils.drawLine now lead to the same copy of the function stored in RAM . . . for i = 1, multishell.getCount() do l(2,i+1,50,i+1,256) -- runs the drawLine function directly = 1 call end
... it'll actually run even faster, because referencing paintutils.drawLine involves a lookup into the paintutils table - but if you save the function pointer directly into l, then calling l skips that table lookup in future!
Localising the l variable should speed things up further when you go to use it.
Edit:
Then there's this sort of thing:
function box(x,y,endx,endy,color) for i = 1,(endx - x + 1),1 do for j = 1,(endy - y + 1),1 do p(x - 1 + i, y - 1 + j,color) -- p calls paintutils.drawPixel() end end end
Consider what the drawPixel function does: it moves the cursor, it sets the background colour, then it draws a single space. Drawing a 10x10 box would call it a hundred times. That's a hundred times you're moving the cursor, a hundred times you're setting the background colour, and a hundred individual calls you're making to draw spaces.
Now let's say you did it like this:
function box(x,y,endx,endy,color)
term.setBackgroundColour(color)
for j = y, endy do
term.setCursorPos(x, j)
term.write(string.rep(" ", endx - x + 1))
end
end
You'd only set the background colour once, and only trigger one cursor-move and screen-write per line.
Edited by Bomb Bloke, 21 January 2015 - 03:20 AM.
1 user(s) are reading this topic
0 members, 1 guests, 0 anonymous users











