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

Please help me find the problem...

Started by KingofGamesYami, 07 January 2015 - 05:36 PM
KingofGamesYami #1
Posted 07 January 2015 - 06:36 PM
local tButton = {
	isClicked = function( self, x, y )
		return true and self.x <= x and self.maxx > x and self.y <= y and self.y + 3 > y or false
	end,
	render = function( self, bColor, tColor )
		term.setBackgroundColor( bColor )
		term.setTextColor( tColor )
		for i = 0, 2 do
			term.setCursorPos( self.x, self.y + i )
			term.write( string.rep( " ", self.maxx - self.x ) )
		end
		term.setCursorPos( math.ceil( (self.maxx + self.x - #self.str)/ 2 ), self.y + 1 )
		term.write( self.str )
	end,
}

local function newButton( x, y, maxx, str )
	local button = { x = x, y = y, maxx = maxx, str = str }
	setmetatable( button, { __index = tButton } )
	return button
end

local function getClicked( tButtons, x, y )
	for _, button in ipairs( tButtons ) do
		if button:isClicked( x, y ) then
			return button.str
		end
	end
end

local tPages = {
	render = function( self )
		term.setBackgroundColor( self.backgroundColor )
		term.clear()
		for k, v in pairs( self[ self.current ] ) do
			v:render( self.bColor, self.bTextColor )
		end
	end,
	
	handleEvents = function( self, ... )
		local event = { ... }
		if event[ 1 ] == "mouse_click" then
			local clicked = getClicked( self[ self.current ], event[ 3 ], event[ 4 ] )
			if clicked then
				if clicked == ">" then
					self.current =  self.current + 1
					term.setBackgroundColor( self.backgroundColor )
					term.clear()
					self:render()
				elseif clicked == "<" then
					self.current = self.current - 1
					term.setBackgroundColor( self.backgroundColor )
					term.clear()
					self:render()
				else
					return "button_click", clicked
				end
			else
				return ...
			end
		end
		return ...
	end,
}

function makeButtonPages( backgroundColor, bColor, bTextColor, ... )
	local maxx, maxy = term.getSize()
	local tStrings = { ... }
	local maxStringLen = 0
	for k, v in pairs( tStrings ) do
		if #v > maxStringLen then
			maxStringLen = #v
		end
	end
	if #tStrings < 1 then
		error( "Not enough arguments", 2 )
	end
	local tButtonPages = {{}}
	local x = math.ceil( maxx / 2 - maxStringLen / 2 ) - 1
	local nMax = x + maxStringLen + 2
	local y = 3
	for k, v in pairs( tStrings ) do
		if y + 3 >= maxy then
			tButtonPages[ #tButtonPages + 1 ] = {}
		end
		tButtonPages[ #tButtonPages ][ #tButtonPages[ #tButtonPages ] + 1 ] = newButton( x, y, nMax, v )
		y = y + 4
	end
	for k, v in ipairs( tButtonPages ) do
		if k ~= 1 then
			v[ #v + 1 ] = newButton( 1, 2, math.ceil( maxy / 2 + 1 ), "<" )
		end
		if k ~= #tButtonPages then
			v[ #v + 1 ] = newButton( maxx - 2, maxx, math.ceil( maxy / 2 ), ">" )
		end
	end
	tButtonPages.backgroundColor = backgroundColor
	tButtonPages.bColor = bColor
	tButtonPages.bTextColor = bTextColor
	tButtonPages.current = 1
	return setmetatable( tButtonPages, { __index = tPages } )
end

local menu = makeButtonPages( colors.lightBlue, colors.blue, colors.green, "Click Me!", "Test", "Hello", "This one is really long", "Page_2" )

menu:render()

while true do
	local event = { menu:handleEvents( os.pullEvent() ) }
	if event[ 1 ] == "button_click" then
		term.clear()
		term.setCursorPos( 1, 1 )
		print( event[ 2 ] )
		error()
	end
end

Now that you've seen my ugly wall of code I'm testing, here's the frustrating error.

[string "term"]:7: bad argument #1 to '?' (number expected, got nil)

AFAIK, this doesn't give me a reference I should be looking at, other than this is me passing a nil to term.setCursorPos. I wish I knew which line, since I could trace from there, but there's not much I can do. (Btw, is there any particular reason it doesn't give me the line number? If there isn't, could I suggest this be changed?)


Ok, figured that out. Now it's just not drawing anything.

Edit: Updated code, but now pages aren't working. More details in last post.
Edited on 07 January 2015 - 11:17 PM
Lyqyd #2
Posted 07 January 2015 - 06:43 PM
Might be easier to use some debug prints to a different term object (the terminal, an attached monitor, wherever) to narrow down which line is causing the error.
KingofGamesYami #3
Posted 07 January 2015 - 07:21 PM
Update: got it to stop erroring, but it doesn't draw anything.
wieselkatze #4
Posted 07 January 2015 - 07:38 PM
Okay, I think you would want it like so?

Spoiler

local tButton = {
	isClicked = function( self, x, y )
		return true and self.x <= x and self.maxx > x and self.y <= y and self.y + 3 > y or false
	end,
	render = function( self, bColor, tColor )
		term.setBackgroundColor( bColor )
		term.setTextColor( tColor )
			for i = 0, 2 do
				term.setCursorPos( self.x, self.y + i )
				term.write( string.rep( " ", self.maxx - self.x ) )
			end
		term.setCursorPos( math.ceil( (self.maxx - self.x) / 2 - #self.str / 2 ) + self.x, self.y + 1 ) --# Forgot to add self.x
		term.write( self.str )
	end,
}

local function newButton( x, y, maxx, str )
	local button = { x = x, y = y, maxx = maxx, str = str }
	setmetatable( button, { __index = tButton } )
	return button
end

local function getClicked( tButtons, x, y )
	for _, button in ipairs( tButtons ) do
		if button:isClicked( x, y ) then
			return button.str
		end
	end
end

local tPages = {
	render = function( self )
		for k, v in pairs( self[ self.current ] ) do
			v:render( self.bColor, self.bTextColor )
		end
	end,

	handleEvents = function( self, ... )
	local event = { ... }
		if event[ 1 ] == "mouse_click" then
			local clicked = getClicked( self[ self.current ], event[ 2 ], event[ 3 ] )
			if clicked then
				if clicked == ">" then
					self.current =  self.current + 1
					term.setBackgroundColor( self.backgroundColor )
					term.clear()
					self:render()
				elseif clicked == "<" then
					self.current = self.current - 1
					term.setBackgroundColor( self.backgroundColor )
					term.clear()
					self:render()
				else
					return "button_click", clicked
				end
			else
				return ...
			end
		end
		return ...
	end,
}

function makeButtonPages( backgroundColor, bColor, bTextColor, ... )
	local maxx, maxy = term.getSize()
	local tStrings = { ... }
	local maxStringLen = 0
	for k, v in pairs( tStrings ) do
		if #v > maxStringLen then
			maxStringLen = #v
		end
	end
	if #tStrings < 1 then
		error( "Not enough arguments", 2 )
	end
	local tButtonPages = {{}}
	local x = math.ceil( maxx / 2 - maxStringLen / 2 ) - 1
	local nMax = x + maxStringLen + 2
	local y = 2
	for k, v in pairs( tStrings ) do
		if #tButtonPages[ #tButtonPages ] * 4 > maxy then
			tButtonPages[ #tButtonPages + 1 ] = {}
		end
		tButtonPages[ #tButtonPages ][ #tButtonPages[ #tButtonPages ] + 1 ] = newButton( x, y, nMax, v ) --# Here
		y = y + 3
	end
	for k, v in pairs( tButtonPages ) do
		if k > 1 then
			v[ #v + 1 ] = newButton( 1, 1, math.ceil( maxy / 2 + 1 ), "<" )
		end
		if k < #tButtonPages then
			v[ #v + 1 ] = newButton( maxx, maxx, math.ceil( maxy / 2 + 1 ), ">" )
		end
	end
	tButtonPages.backgroundColor = backgroundColor
	tButtonPages.bColor = bColor
	tButtonPages.bTextColor = bTextColor
	tButtonPages.current = 1
	return setmetatable( tButtonPages, { __index = tPages } )
end

local menu = makeButtonPages( colors.black, colors.blue, colors.green, "Click Me!", "Test", "Hello" )
term.clear()
menu:render()

while true do
	local event = { menu:handleEvents( os.pullEvent() ) }
	if event[ 1 ] == "button_click" then
		term.clear()
		term.setCursorPos( 1, 1 )
		print( event[ 2 ] )
		error()
	end
end

In line 12 of the drawing function you actually forgot to add the first x-coordinate to the cursor position - leading to the text being at the left of the screen.
Other that that your error was using tButtonPages[ #tButtonPages ] instead of tButtonPages[ #tButtonPages ][ #tButtonPages[ #tButtonPages ] + 1 ] in line 84.
This was leading to buttons being created as pages - you forgot to put the buttons inside the tables.
You might also increase y by four on every addition to leave spaces between the buttons.
Edited on 07 January 2015 - 06:44 PM
KingofGamesYami #5
Posted 07 January 2015 - 09:54 PM
-snip-

…Working on it. I figured out the drawing problem.
Edited on 07 January 2015 - 09:04 PM
KingofGamesYami #6
Posted 08 January 2015 - 12:19 AM
Update: I got it working, except my right/left buttons aren't working for some reason. I've used some error statements to see what has happened, and it is correctly inserting a new button into the table. I haven't been able to test the left button, but the right button is defiantly broken.
Bomb Bloke #7
Posted 08 January 2015 - 07:35 AM
Not sure if this is your issue, but this is your button constructor:

local function newButton( x, y, maxx, str )  -- No mention of maxy.

And these are the calls you're using to build the arrow buttons:

                        v[ #v + 1 ] = newButton( 1, 2, math.ceil( maxy / 2 + 1 ), "<" )  -- ... maxy?
                        ...
                        v[ #v + 1 ] = newButton( maxx - 2, maxx, math.ceil( maxy / 2 ), ">" )

Speaking of which, instead of having an extra loop for those calls, perhaps move them up into this block:

        for k, v in pairs( tStrings ) do
                if y + 3 >= maxy then
                        tButtonPages[ #tButtonPages ][ #tButtonPages[ #tButtonPages ] + 1 ] = newButton( maxx - 2, maxx, math.ceil( maxy / 2 ), ">" )
                        tButtonPages[ #tButtonPages + 1 ] = {}
                        tButtonPages[ #tButtonPages ][ 1 ] = newButton( 1, 2, math.ceil( maxy / 2 + 1 ), "<" )
                end
                tButtonPages[ #tButtonPages ][ #tButtonPages[ #tButtonPages ] + 1 ] = newButton( x, y, nMax, v )
                y = y + 4
        end
KingofGamesYami #8
Posted 08 January 2015 - 01:27 PM
My creating function takes x, maxx, y, and text. I am attempting to position it halfway down the screen, so I give it a y of half maxy.

I think I'll take your suggestion about the loop though.
Bomb Bloke #9
Posted 08 January 2015 - 01:48 PM
Maybe you should take another look at the order in which it takes those parameters, and the order in which you're supplying them.
KingofGamesYami #10
Posted 08 January 2015 - 02:06 PM
*facepalm*

I am so stupid. How did I not notice this?



Fixing stuff in the code now.
Edited on 08 January 2015 - 01:06 PM