This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
KingofGamesYami's profile picture

Redirect Object Help

Started by KingofGamesYami, 28 November 2014 - 03:20 PM
KingofGamesYami #1
Posted 28 November 2014 - 04:20 PM
My redirect object simply is not writing text in the appropriate places, and I wanted to figure out why.

Relevant part

	new.write = function( sText )
		local x,y = new.parent.getCursorPos()
		local px, py = new.getPosition()
		local tx, ty = new.getCursorPos()
		local toWrite = sText--:sub( 1, new.sizex - tx ) --#commented out the sub because it entirely deletes the text... IDK why though.
		new.parent.setCursorPos( px + tx - 1, py + ty - 1 )
		new.parent.setTextColor( new.tColor )
		new.parent.setBackgroundColor( new.bColor )
		new.parent.write( toWrite )
		new.setCursorPos( tx + #tWrite, ty )
	end
Dog #2
Posted 28 November 2014 - 04:52 PM
I have a guess as to why your sub is 'deleting' text. You're subtracting tx (current cursor pos) from new.sizex. If your new size is smaller than your cursor pos, you're going to end up with a negative value for your sub. I'm guessing you want to actually subtract the difference in size from either the new size or the cursor pos…or something similar? Apologies if I'm off-base with this.
KingofGamesYami #3
Posted 28 November 2014 - 05:30 PM
I'm trying to not draw text outside the window's right edge. The cursor shouldn't be outside the window.

I'm thinking that problem is caused by some other problem somewhere, because it doesn't work even with that part commented out.
KingofGamesYami #4
Posted 28 November 2014 - 08:51 PM
Well, this is getting nowhere so I'll post the entire code…

Spoiler

local bigx, bigy = term.getSize() --note: this will need changed.

function init( win, posx, posy, sizex, sizey, title )
	local new = {parent = win, posx = posx, posy = posy, sSizex = sizex, sSizey = sizey, x = 1, y = 1, title = title, tColor = colors.white, bColor = colors.black, state = "small", internal = {} }
	
	for y = 1, sizey do
		new.internal[ y ] = {}
		for x = 1, sizex do
			new.internal[ y ][ x ] = {c=' ',t=colors.white,b=colors.black}
		end
	end
	
	new.isColor = function()
		return new.parent.isColor()
	end
	new.isColour = new.isColor
	
	new.setState = function( state )
		if state ~= "small" and state ~= "large" then
			error( "Invalid state", 2 )
		end
		new.state = state
	end
	
	new.getState = function()
		return new.state
	end
	
	new.getParent = function()
		return new.parent
	end
	
	new.getTitle = function()
		return new.title
	end
	
	new.getSize = function()
		if new.getState() == "small" then
			return new.sSizex, new.sSizey
		else
			return bigx, bigy
		end
	end
	
	new.getPosition = function()
		return new.posx, new.posy
	end
	
	new.getCursorPos = function()
		return new.x, new.y
	end
	
	new.setCursorPos = function( x, y )
		new.x = x
		new.y = y
	end
	
	new.setTextColor = function( color )
		new.tColor = color
	end
	
	new.setTextColour = new.setTextColor
	
	new.setBackgroundColor = function( color )
		new.bColor = color
	end
	
	new.setBackgroundColour = new.setBackgroundColor
	
	new.write = function( sText )
		local x,y = new.parent.getCursorPos()
		local px, py = new.getPosition()
		local tx, ty = new.getCursorPos()
		local mx, my = new.getSize()
		local toWrite = sText:sub( 1, mx - tx + 1 )
		new.parent.setCursorPos( px + tx - 1, py + ty - 1 )
		new.parent.setTextColor( new.tColor )
		new.parent.setBackgroundColor( new.bColor )
		new.parent.write( toWrite )
		new.setCursorPos( tx + #tWrite, ty )
	end
	
	new.clear = function()
		local x, y = new.getSize()
		for i = 1, y do
			new.setCursorPos( 1, i )
			new.write( string.rep( " ", x ) )
		end
	end

	new.scroll = function( nLines )
		if nLines ~= 0 then
			local newsaved, maxx, maxy = {}, new.getSize()
			for x, t in ipairs( new.saved ) do
				for y, pixel in ipairs( t ) do
					local newy = y - nLines
					if newy < 0 and newy > maxy then
						newsaved[ x ][ y ] = pixel
					end
				end
			end
			new.saved = newsaved
		end
	end
	
	new.render = function()
		local x,y = new.parent.getCursorPos()
		local px, py = new.getPosition()
		local tx, ty = new.getCursorPos()
		for x, t in ipairs( new.saved ) do
			for y, pixel in ipairs( t ) do
				--update pixels
				new.setTextColor( pixel.tColor )
				new.setBackgroundColor( pixel.bColor )
				--start render--
				new.parent.setCursorPos( px + tx - 1, py + ty - 1 )
				new.parent.setTextColor( new.tColor )
				new.parent.setBackgroundColor( new.bColor )
				new.parent.write( sText )
				local newx, newy = new.parent.getCursorPos()
				new.x, new.y = newx - x, newy - y
				new.parent.setCursorPos( x, y )
				--end render--
			end
		end
	end

	return new
end

function drawToolBar( app, bColor, tColor )
	local win = app:getWindow()
	local x, y = win.getPosition()
	local sizex, sizey = win.getSize()
	local parent = win.getParent()
	parent.setCursorPos( x, y - 1 )
	parent.setTextColor( tColor )
	parent.setBackgroundColor( bColor )
	parent.write( string.rep( " ", sizex ) )
	parent.setCursorPos( x + math.ceil( (sizex - 3 - #app:getName() ) /2 ) , y - 1 )
	parent.write( app:getName() )
	parent.setCursorPos( sizex + x - 3, y - 1 )
	parent.write( "-" .. ( win.getState() == "small" and "O" or "o" ) )
	parent.setTextColor( colors.white )
	parent.setBackgroundColor( colors.red )
	parent.write( "X" )
end
Bomb Bloke #5
Posted 29 November 2014 - 01:41 AM
Shot in the dark guess, as you haven't exactly specified how this is failing, but that "tWrite" typo may well have something to do with it.
theoriginalbit #6
Posted 29 November 2014 - 02:21 AM
also a lot of these from what I can see could just be using the parent.

and your parent could just be done with metatables, take this example which overrides a single function in the term and leaves everything else to use the last term (definitely better that writing all the functions)

local oldTerm = term.current()
local newTerm = setmetatable({
  setTextColor = function( c )
    --# pretend some validation is performed here
    oldTerm.setTextColor( c )
  end;
}, oldTerm)
newTerm.setTextColour = newTerm.setTextColor --# the EN_UK/AU version override too

--# redirect will accept the object as the old functions (with the exception of setting the text colour) can be invoked
term.redirect(newTerm)
I have used this technique in CCTicTacToe
KingofGamesYami #7
Posted 29 November 2014 - 03:14 AM
Alright, this time my internet connection will not eat my reply.

Here's everything.

icemain

local tApps = {}

function drawDock( bColor, tColor )
	local x, y = term.getSize()
	term.setBackgroundColor( bColor )
	term.setTextColor( tColor )
	for i = 1, y do
		term.setCursorPos( 1, i )
		term.write( '   ' )
	end
	local y = 2
	for _, app in pairs( tApps ) do
		app:showIcn( 1, y )
		y = y + 2
	end
end

local app = {
	getName = function( self )
		return self.name
	end,
	getWindow = function( self )
		return self.window
	end,
	getStatus = function( self )
		return coroutine.status( self.co )
	end,
	resume = function( self, ... )
		return coroutine.resume( self.co, ... )
	end,
	showIcn = function( self, px, py )
		for y, line in pairs( self.icn ) do
			for x, c in pairs( line ) do
				term.setCursorPos( px - 1 + x, py - 1 + y )
				term.setTextColor( c.tColor )
				term.setBackgroundColor( c.bColor )
				term.write( c.char )
			end
		end
	end
}

function launch( sFile, sIcn, ... )
	if not fs.exists( sFile ) then
		error( "No such file: " .. sFile, 2 )
	end
	local file = fs.open( sFile, "r" )
	local data = file.readAll()
	file.close()
	local func, err = loadstring( data )
	if not func then
		error( err, 0 )
	end
	local new = {
		name = sFile,
		window = icewindow.init( term.current(), 4, 4, 20, 10, sFile ),
		co = coroutine.create( func ),
		icn = icon.load( sIcn )
	}
	local origin = term.current()
	term.redirect( new.window )
	new.sFilter = coroutine.resume( new.co )
	term.redirect( origin )
	setmetatable( new, { __index = app })
	tApps[#tApps+1] = new
	icewindow.drawToolBar(new,colors.blue,colors.lightBlue)
	return new
end

function run()
	local origin = term.current()
	local tFilters = {}
	local event = {}
	while #tApps > 0 do
		for i, app in ipairs( tApps ) do
			if app.sFilter then
				tFilters[ i ] = app.sFilter
				app.sFilter = nil
			end
			if (not tFilters[ i ] or event[ 1 ] == tFilters[ i ] or event[ 1 ] == "terminate") and app:getStatus() == "suspended" then
				term.redirect( app:getWindow() )
				tFilters[ i ] = app:resume( unpack( event ) )
				term.redirect( term.current() )
				app.tArgs = nil
			elseif app:getStatus() == "dead" then
				table.remove( tApps, i )
				table.remove( tFilters, i )
			end
		end
		event = { os.pullEvent }
	end
end

test

os.loadAPI( "icemain" )
os.loadAPI( "icewindow" )
os.loadAPI( "icon" )
icemain.launch( '.test', '.icn' )
icemain.drawDock( colors.white, colors.lightBlue )
icemain.run()

.test

term.setTextColor( colors.white )
term.setBackgroundColor( colors.lightBlue )
term.clear()

term.setCursorPos( 1, 1 )
print( "Hello World" )

[namedspoiler="Result]
[IMG]http://i.imgur.com/ifFkmeD.png?1[/IMG]
[/namedspoiler]

[b]Edit:[/b] The icon system is bugged, pay no attention to the astrisk in the picture: It has no relevance.
Edited on 29 November 2014 - 02:15 AM
KingofGamesYami #8
Posted 02 December 2014 - 06:11 PM
Anyone have any insights into this?
Lyqyd #9
Posted 02 December 2014 - 07:58 PM
I'll take a look, but a better description would be helpful. If it's not writing "in the right place", where is it writing?
KingofGamesYami #10
Posted 02 December 2014 - 08:35 PM
I'll take a look, but a better description would be helpful. If it's not writing "in the right place", where is it writing?

The post above my last post has a spoiler named "Result" showing exactly what the entire thing is doing at this point: It should be clearing a small portion of the screen below the '.test' toolbar thingy, then printing some text. It is only clearing one line, and refusing to do anything to the rest.

Edit: Here's the spoiler
[namedspoiler="Result]
[IMG]http://i.imgur.com/ifFkmeD.png?1[/IMG]
[/namedspoiler]
[/quote]
Edited on 02 December 2014 - 07:38 PM
Bomb Bloke #11
Posted 03 December 2014 - 03:05 AM
I think you're going to have to bite the bullet, hook up an external monitor, and start writing debug info to that - what is the "write" function attempting to write, what is the text length, which co-ords are being targeted, etc? What screen size is the "clear" function detecting? etc… There are presumably some unexpected values coming in from somewhere, but you'll first have to work out the "where" before you can figure out the "why".

I'd also consider sticking an os.pullEvent("char") into the write function so that you can better track exactly what's happening as it happens.
Bomb Bloke #12
Posted 03 December 2014 - 05:43 AM
Oh, and here's something else worth considering - the script may be crashing.

For whatever reason, Dan rigged the window API (the one used by every advanced computer to render pretty much everything since CC 1.6 dropped, by way of multishell) to occasionally move the cursor out of bounds. Which means that if a script happens to error while it's out there, you won't see the contents of the error message.

So let's say, for example, you didn't bother to fix that typo I pointed out to you earlier - as soon as you try to get the length of a nil object, the whole thing'll crash, and thanks to the window API you may not see the error message.

If, on the other hand, you DID fix that, then you might consider randomly dotting term.setCursorPos(1,1) lines through your script (so that if it's still crashing, you've got a better chance of having the message rendered somewhere visible).