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

New button that can be pressed while other buttons are active

Started by LuffyNL, 22 March 2014 - 06:59 PM
LuffyNL #1
Posted 22 March 2014 - 07:59 PM
Hey there,

About a year ago a guy called FremNet made this program:
http://pastebin.com/rdUQhd8a

I tried making some improvements and everything works except for the monitor,
I am trying to add a button in the bottom right of the monitor that sais shuffle and when I press it it lights up green for 5 seconds and then turns back to gray, but while it is doing this I want to be able to press the other buttons.

I have tried several things but everything got messy and didn't work.

If anyone could show me how to go about this that would be great!

Thanks in advance :)/>
CometWolf #2
Posted 22 March 2014 - 08:29 PM
Should be easy enough, just use timers.

--drawbutton
local colorButtonTimer --localize the variable for the timer
local tEvent = {os.pullEvent()} --get events
  if tEvent[1] == "mouse_click" then
	if pressedButton then --you get the idea
	  --draw the button as a different color
	  colorButtonTimer = os.startTimer(5) --This function starts a timer, and returns it's id. When the given time has elapsed, a timer event with the id as the first param will be fired.
	end
  elseif tEvent[1] == "timer" then --a timer event has fired
	if tEvent[2] == colorButtonTimer then --compare the id to the colorButtonTimer id, if it's a match it means the corresponding timer has elapsed.
	  --draw button as original color again
	end
  end
end
Edited on 22 March 2014 - 07:31 PM
LuffyNL #3
Posted 22 March 2014 - 09:02 PM
Thanks a bunch, that solves the timer issue but I am having trouble drawing the button twice, either it removes all the text on the same line or it first writes the text and then writes the text directly after it in a different color
CometWolf #4
Posted 22 March 2014 - 09:35 PM
You're gonna have to show your code if you want help with that.
LuffyNL #5
Posted 22 March 2014 - 09:42 PM

monitorSide = "front"
radioSide   = "back"

startTime = 0
jbRunTime = 0
turtleId  = 0
discInfo  = nil
state	 = "startup"
monitor   = nil

function checkPeripheral(side, type)
if not(peripheral.isPresent(side) and peripheral.getType(side) == type) then
  print("Please attach a " .. type .. " to the " .. side .. " side")
  exit()
end
end

function renderButton(text, active, state)
if state == active then
  monitor.setTextColor(colors.green)
  monitor.write(text)
else
  monitor.setTextColor(colors.gray)
  monitor.write(text)
end
end

function renderShuffleButton(text, status)
if status == "Shuffling" then
monitor.setTextColor(colors.green)
monitor.write(text)
sleep(3)
status = "status"
renderFooter(state)
else
monitor.setTextColor(colors.gray)
monitor.write(text)
end
end

function renderFooter(state)
monitor.clearLine()
monitor.setCursorPos(22,5)

renderButton("[]", "stopped", state)
renderButton("<<", "rewind", state)
renderButton(">>", "forward", state)
renderButton("[>", "playing", state)
monitor.setCursorPos(35,5)
renderShuffleButton("Shuffle", status)
status = "status"
end

function transmit(action)
rednet.send(turtleId, textutils.serialize({type="jukebox", action=action}))
end

function checkButton(x, y)
if y == 5 then
  if x == 22 or x == 23 then
   transmit("stop")
  elseif x == 24 or x == 25 then
   transmit("prev")
   state = "rewind"
  elseif x == 26 or x == 27 then
   transmit("next")
   state = "forward"
  elseif x == 28 or x == 29 then
   transmit("play")
  elseif x == 35 or x == 36 then
   transmit("shuffle")
   status = "Shuffling"
  end

  renderFooter(state)
end
end

function renderDuration()
monitor.setCursorPos(2,3)
monitor.clearLine()
local timeLeft = math.floor(discInfo['duration'] - (jbRunTime + (os.clock() - startTime)))
if timeLeft < 0 then
  timeLeft = 0
end

monitor.write(discInfo['duration'] .. "/" .. timeLeft)
end

checkPeripheral(monitorSide, "monitor")
checkPeripheral(radioSide, "modem")
monitor = peripheral.wrap(monitorSide)
monitor.clear()
monitor.setCursorPos(1,1)
monitor.write("Startup....")
monitor.setCursorPos(2,1)
monitor.write("Looking for jukebox...")
rednet.open(radioSide)
rednet.broadcast(textutils.serialize({action="announce", type="jukebox", device="monitor"}))
countDownTimer = os.startTimer(1)
while true do
ev,p1,p2,p3 = os.pullEvent()
if ev == "rednet_message" then
  data = textutils.unserialize(p2)
  if data["type"] == "jukebox" then
   if data["action"] == "acknowledge" or (data["action"] == "announce" and data["device"] == "jukebox") then
	turtleId = p1
	if data["action"] == "announce" then
	 -- say hi back
	 rednet.send(computerId, textutils.serialize({type="jukebox", action="acknowledge"}))
end
   elseif data["action"] == "playing" then
	if not(state == "playing") then
	 monitor.clear()
	 monitor.setCursorPos(1,1)
	 monitor.setTextColor(colors.gray)
	 monitor.write("Now playing:")
	 state="playing"
	 renderFooter(state)
 end
	monitor.setCursorPos(2,2)
	monitor.clearLine()
	monitor.setTextColor(colors.white)
	discInfo = data["discInfo"]
	monitor.write(data["discInfo"]["title"])
	jbRunTime = data["runTime"]
	startTime = os.clock()
	renderDuration()
   elseif data["action"] == "stopped" then
	if not(state == "stopped") then
	 monitor.clear()
	 monitor.setCursorPos(1,1)
	 monitor.setTextColor(colors.gray)
	 monitor.write("Stopped...")
	 state="stopped"
	 renderFooter(state)
	end
   end
  end
elseif ev == "timer" then
  currentTimer = os.startTimer(1)
  if state == "playing" then
   renderDuration()
  end
elseif ev == "monitor_touch" then
  checkButton(p2, p3)
end
end

This is what I tried
Edited on 22 March 2014 - 08:43 PM
CometWolf #6
Posted 22 March 2014 - 10:33 PM
Obviously clearLine is gonna clear the line… From what i can tell you're not setting any color on it though?

function renderDuration()
  monitor.setCursorPos(2,3)
  monitor.clearLine()
  local timeLeft = math.floor(discInfo['duration'] - (jbRunTime + (os.clock() - startTime)))
  if timeLeft < 0 then
    timeLeft = 0
  end
  monitor.write(discInfo['duration'] .. "/" .. timeLeft)
end
LuffyNL #7
Posted 23 March 2014 - 10:31 AM
Oh no, that is not the part I wrote, this is the part


function renderShuffleButton(text, status)
if status == "shuffling" then
monitor.setTextColor(colors.green)
monitor.write(text)
sleep(3)
status = "status"
renderFooter(state)
monitor.setTextColor(colors.gray)
else
monitor.setTextColor(colors.gray)
monitor.write(text)
end
end
function renderFooter(state)
monitor.clearLine()
monitor.setCursorPos(22,5)
renderButton("[]", "stopped", state)
renderButton("<<", "rewind", state)
renderButton(">>", "forward", state)
renderButton("[>", "playing", state)
monitor.setCursorPos(35,5)
renderShuffleButton("Shuffle", status)
status = "status"
end

function checkButton(x, y)
if y == 5 then
  if x == 22 or x == 23 then
   transmit("stop")
  elseif x == 24 or x == 25 then
   transmit("prev")
   state = "rewind"
  elseif x == 26 or x == 27 then
   transmit("next")
   state = "forward"
  elseif x == 28 or x == 29 then
   transmit("play")
  elseif x == 35 or x == 36 then
   transmit("shuffle")
   status = "shuffling"
  end

It's about the shuffle button
I haven't put the time in yet, I first want to make sure I can properly make the text appear
CometWolf #8
Posted 23 March 2014 - 11:12 AM
I don't really see much here that would explain what you're expirencing, aside from not setting the cursor position prior to clearing the line. What's the current issue with this piece of code? And my god what a messy piece of code this is.

function renderShuffleButton(text, status)
  if status == "shuffling" then
	monitor.setTextColor(colors.green)
	monitor.write(text)
	sleep(3) --your program will cease to function during this, im assuming that was the original issue.
	status = "status"
	renderFooter(state)-- This function clears whatever line the cursor is currently on, renders the other buttons and then calls renderShuffleButton again with the new status of "status,
	monitor.setTextColor(colors.gray)
  else --meaing that this is executed
	monitor.setTextColor(colors.gray)
	monitor.write(text)
  end
end
function renderFooter(state)
  monitor.setCursorPos(22,5) --moving this above the clearLine
  monitor.clearLine()
  renderButton("[]", "stopped", state)
  renderButton("<<", "rewind", state)
  renderButton(">>", "forward", state)
  renderButton("[>", "playing", state)
  monitor.setCursorPos(35,5)
  renderShuffleButton("Shuffle", status)
  status = "status"
end
Edited on 23 March 2014 - 10:12 AM
LuffyNL #9
Posted 23 March 2014 - 11:23 AM
I indeed made it really messy, I'll start over from the point where I started messing things up and then see what the results will be
CometWolf #10
Posted 23 March 2014 - 11:36 AM
Both you and the guy who made this originally should probably learn to use local variables. As for you specifically, i'd start with some more sensible variable names. state and status is pretty much the same. Something like shuffleStatus would make far more sense.
LuffyNL #11
Posted 23 March 2014 - 01:38 PM
I managed so get it to working somehow, thanks for all the help and I´ll do best