Advertisement
HPWebcamAble

[CC API][2.0] Screen API

Feb 19th, 2015
2,815
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 14.19 KB | None | 0 0
  1. --[[
  2. Coded By HPWebcamAble
  3.  
  4. ==== Description ====
  5. This is my Screen API
  6.  
  7. It allows you to add shapes (called Objects) and Click Areas to Screens
  8. You can have as many Screens as you want.
  9. See the CC Forum Post in 'Documentation' for a quick start guide
  10.  
  11.  
  12. ==== Documentation ====
  13. Computer Craft Forum Post:
  14. http://www.computercraft.info/forums2/index.php?/topic/22061-screen-api/
  15.  
  16. Scroll down to 'Functions and How to Use Them' for info on each function
  17.  
  18. Remember, only 'draw' and 'drawObject' actually change anything on the monitor/computer's physical screen
  19.  
  20.  
  21. ==== Installation ====
  22. Pastebin Code:4j4mJsWw
  23.  
  24. This won't do anything on its own. You use this to help write your programs
  25.  
  26. You have two options:
  27. 1. Copy and paste the functions into your program and call them like you would normally call a function
  28. 2. In your program, call os.loadAPI("filename"), then call functions with filename.functionName()
  29.  
  30.  
  31. ==== Update History ====
  32. The pastebin will always have the latest version
  33.  
  34. |2.0|
  35. -Each individual screen is an object now
  36.   *You still call the functions with a period (.), not a colon (:)
  37.   *Note that the default elements are universal, they are the same for every screen you make
  38. -Cleaned up the code
  39. -Slightly changed how text is centered on objects (again)
  40.   *Should be centered, or 1 pixel to the left if that isn't possible
  41. -Removed 'state', replaced with 'visble' (objects only) and 'clickable'
  42.   *Added toggleVisible function for Objects
  43.   *Added toggleClickable function for both element types
  44.   *Removed toggleState function
  45. -Added getObject and getClickArea to allow changing of text, position, etc
  46. -Updated documentation (See 'Functions and How to Use Them' below)
  47.  
  48. |1.3|
  49. -Changed how object states are stored in preparation for Simple Screen Maker 2!
  50. -Touched up the documentation section
  51. -Fixed a few typos
  52. -toFill function now recognizes false values
  53.  
  54. |1.2.5|
  55. -Fixed a slight bug when drawing text on an object
  56.   *It now centers correctly
  57.  
  58. |1.2.4|
  59. -Fixed text sometimes being drawn off center
  60. -Added setObjectText
  61.  
  62. |1.2.3|
  63. -Fixed a *kinda* major issue with drawing objects
  64.   *A row of pixels was always missing on the right side
  65. -The default for 'hasClickArea' for objects is now 'false'
  66.  
  67. |1.2.2|
  68. -Function descriptions are now in 'Functions and How to Use Them' section
  69. -handleEvents can now trigger 'object' events (Same arguments as Click Areas)
  70. -checkPos now returns "click_area" or "object" and its name or the result of its action
  71. -Fixed bug that caused 'off' objects to be triggered when clicked
  72.   *Objects no longer make a click area when created, both object boundries and click area boundries are checked by checkPos
  73.  
  74. |1.2.1|
  75. -Fixed bug that caused the text of a button to be put in weird places
  76.  
  77. |1.2|
  78. -Changed 'checkPos' to 'handleEvents'
  79.   *Use instead of os.pullEvent()
  80.   *If a Click Area is clicked, it triggers the event 'click_area' (if it doens't have a function)
  81.     -Arguments are name,mouse button
  82. -'toggleObject' enables or disables an object
  83. -'toggleObjectState' is what makes an object use on or off
  84.  
  85. |1.1|
  86. -Added a default object and clickArea
  87.   *If you leave out something when adding, the values will be filled in
  88.   *You can change the defaults with setDefaultObject and setDefaultClickArea
  89. -Added much more descriptive errors
  90. -Added a 'drawObject' function, to draw a single object
  91. -Fixed a few bugs with the states of Click Areas
  92.  
  93. |1.0|
  94. -Release
  95.  
  96.  
  97. ==== Functions and How to Use Them ====
  98.  
  99. API Functions (The API has these):
  100.  
  101. new(nBackground)
  102.   Creates a new screen, and returns its pointer
  103.  
  104.   If you supply a background, the computer's screen will be cleared each time
  105.     you call draw(). Otherwise, the screen will not be cleared.
  106.  
  107.    
  108. Screen Functions (Only screen object have these):
  109.  
  110. handleEvents(bUseRaw)
  111.   *Use this in place of os.pullEvent()*
  112.   It will automatically check if mouse_click events are in an Object or Click Area
  113.   If an element has an action, it will return nil
  114.   If not, it returns:
  115.   <type of element>,<name>,<mouse button used>
  116.  
  117.   If an element wasn't clicked, it returns an event like os.pullEvent would
  118.   Pass true to bUseRaw to use os.pullEventRaw() instead of os.pullEvent()
  119.  
  120. checkPos(x,y)
  121.   Called by handleEvents
  122.   Checks if  <x> and <y> are in an Object or Click Area
  123.   If something was clicked and it had an action, it returns:
  124.   true,true,<result of action function>
  125.  
  126.   If it didn't have an action:
  127.   true,false,<element type>,<name>
  128.  
  129.   If nothing was clicked, it returns false
  130.  
  131. draw()
  132.   Clears the screen, if a background was supplied when the screen was created
  133.   Calls 'drawObject' for each object
  134.  
  135.  
  136. Click Areas:
  137.  
  138. Example Click Area Info:
  139. {
  140.   name = "ClickAreaExample", --String, stored by name. If not specified, its name is set to '<x>:<y>'
  141.   minX = 1, --int, the smallest X coordinate, the farthest left side of the button
  142.   maxX = 5, --int, the largest X coordinate, the farthest right side of the button
  143.   minY = 1, --int, the smallest Y coordinate, the highest part of the button
  144.   maxY = 3, --int, the largest Y coordinate, the lowest part of the button
  145.   action = function() print("HI") end --What happens if the area is clicked. Optional
  146. }
  147.  
  148. addClickArea(clickAreaInfo)
  149.   <clickAreaInfo> is a table that describes the Click Area
  150.   Leaving out a value will use the default (See the default table below)
  151.  
  152. toggleClickArea(name)
  153.   Enables or disables a Click Area
  154.   Disabled Click Areas aren't triggered when clicked
  155.   Returns the new state (true or false)
  156.  
  157. setDefaultClickArea(clickAreaInfo)
  158.   Sets the default Click Area
  159.   Any values that are left out when creating a Click Area
  160.     are filled in with the existing default Click Area
  161.    
  162. getClickArea(name)
  163.   Returns the pointer of a Click Area so that its various fields can be
  164.     modified
  165.  
  166.  
  167. Object Functions:
  168.  
  169. Example Object Info:
  170. {
  171.   text = "test", --string, what the object shows, use false or nil for nothing
  172.   name = "Example", --string, the object is stored by its name. Use this to manipulate the object
  173.   minX = 1, --int, the smallest X coordinate, the farthest left side
  174.   maxX = 5, --int, the largest X coordinate, the farthest right side
  175.   minY = 1, --int, the smallest Y coordinate, the highest part
  176.   maxY = 3, --int, the largest Y coordinate, the lowest part
  177.   states = { --table, a list of possible states the object can have
  178.     on = {text = colors.black, back = colors.white}, --table, this state is called 'on', the text will be black and the background of the object will be white
  179.     off = {text = colors.white, back = colors.black} --table, this state is called 'off', it is the opposite of 'on' (though it can be any colors you want)
  180.   },
  181.   hasClickArea = true --boolean, true if the object should be clickable
  182.   action = function() print("HI") end --function, runs if the object is clicked. Only works if hasClickArea is true
  183.   state = "on" --string, what state the object should start in
  184. }
  185.  
  186. addObject(objectInfo)
  187.   <objectInfo> is a table that describes the Object
  188.   Leaving out a value of <objectInfo> will use the default (See default table below)
  189.  
  190. drawObject(name)
  191.   Draws a single Object
  192.   Skips objects that aren't visible
  193.  
  194. toggleObjectState(name,screen)
  195.   Note that this is NOT toggleObject
  196.   Turns on object on or off
  197.   Leaving <screen> blank will use the default screen
  198.   Returns the new state (true or false)
  199.  
  200. toggleObjectState(name)
  201.   Toggles between an Object's states
  202.   NOTE: Only works if the Object has exactly two states
  203.   Returns the new state
  204.  
  205. toggleObjectVisible(name)
  206.   Objects that aren't visible will be skipped by 'drawObject'
  207.   Returns new state (true or false)
  208.  
  209. toggleObjectClickable(name)
  210.   Objects that aren't clickable will be skipped by 'checkPos'
  211.   Returns new state (true or false)
  212.  
  213. setDefaultObject(objectInfo)
  214.   Sets the default object
  215.   Any values that are left out will be filled in with the default object
  216.  
  217. getObject(name)
  218.   Returns the pointer of an Object so that its various fields can be
  219.     modified
  220. ]]
  221.  
  222. local default = {
  223.   object = {
  224.     text = nil,
  225.     name = "default",
  226.     minX = 1,minY = 1,
  227.     maxX = 7,maxY = 3,
  228.     states = {
  229.       on = {text = colors.white, back = colors.lime},
  230.       off = {text = colors.white, back = colors.red}
  231.     },
  232.     clickable = false,
  233.     visible = true,
  234.     state = "off",
  235.     action = nil
  236.   },
  237.   clickArea = {
  238.     name = "default",
  239.     minX = 1,minY = 1,
  240.     maxX = 5,maxY = 3,
  241.     clickable = true,
  242.     action = nil
  243.   }
  244. }
  245.  
  246. local function fillTable(toFill,fillWith) --Used by the API
  247.   if toFill == nil then toFill = {} end
  248.   for a,b in pairs(fillWith) do
  249.     if type(b) == "table" then
  250.       toFill[a] = fillTable(toFill[a],b)
  251.     else
  252.       toFill[a] = toFill[a]==nil and b or toFill[a]
  253.     end
  254.   end
  255.   return toFill
  256. end
  257.  
  258. local function countIndexes(tbl) --Also used by API
  259.   local total = 0
  260.   for a,b in pairs(tbl) do total = total+1 end
  261.   return total
  262. end
  263.  
  264. local function assert(check,err,lvl)
  265.   lvl = lvl or 2
  266.   if not check then error(err,lvl+1) end
  267.   return check
  268. end
  269.  
  270. function new(nBackground)
  271.   local api = {}
  272.   local objects = {}
  273.   local clickAreas = {}
  274.   local background = nBackground
  275.  
  276.   function api.checkPos(x,y)
  277.     x,y = tonumber(x),tonumber(y)
  278.     assert(x and y,"expected number,number")
  279.     for name,data in pairs(clickAreas) do
  280.       if x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY and data.clickable then
  281.         if type(data.action)=="function" then return true,true,data.action()
  282.         else return true,false,"click_area",name end
  283.       end
  284.     end
  285.     for name,data in pairs(objects) do
  286.       if data.clickable and data.visible and x >= data.minX and x <= data.maxX and y >= data.minY and y <= data.maxY then
  287.         if type(data.action)=="function" then return true,true,data.action()
  288.         else return true,false,"object",name end
  289.       end
  290.     end
  291.     return false
  292.   end
  293.  
  294.   function api.handleEvents(bUseRaw)
  295.     local pull = bUseRaw and os.pullEventRaw or os.pullEvent
  296.     local event = {pull()}
  297.     if event[1] == "mouse_click" then
  298.       local wasElement,hadFunction,elementType,name = api.checkPos(event[3],event[4])
  299.       if wasElement then
  300.         if not hadFunction then
  301.           return elementType,name,event[2]
  302.         else return nil
  303.         end
  304.       end
  305.     end
  306.     return unpack(event)
  307.   end
  308.  
  309.   function api.setDefaultObject(newDefaultObject)
  310.     assert(type(newDefaultObject)=="table","expected table, got "..type(newDefaultObject))
  311.     default.object = fillTable(newDefaultObject,default.object)
  312.   end
  313.  
  314.   function api.setDefaultClickArea(newDefaultClickArea)
  315.     assert(type(newDefaultClickArea)=="table","expected table, got "..type(newDefaultClickArea))
  316.     default.clickArea = fillTable(newDefaultClickArea,default.clickArea)
  317.   end
  318.  
  319.   function api.draw()
  320.     if background then term.setBackgroundColor(background) term.clear() end
  321.     for name,data in pairs(objects) do
  322.       api.drawObject(name)
  323.     end
  324.   end
  325.  
  326.   function api.addClickArea(clickAreaInfo)
  327.     assert(type(clickAreaInfo)=="table","expected table, got "..type(clickAreaInfo))
  328.     fillTable(clickAreaInfo,default.clickArea)
  329.     assert(clickAreas[clickAreaInfo.name]==nil,"an object with the name '"..clickAreaInfo.name.."' already exists")
  330.     clickAreas[clickAreaInfo.name] = clickAreaInfo
  331.   end
  332.  
  333.   function api.toggleClickArea(name)
  334.     assert(clickAreas[name]~=nil,"Click Area '"..name.."' doesn't exist")
  335.     clickAreas[name].clickable = not clickAreas[name].clickable
  336.     return clickAreas[name].clickable
  337.   end
  338.  
  339.   function api.getClickArea(name)
  340.     assert(clickAreas[name]~=nil,"Click Area '"..name.."' doesn't exist")
  341.     return clickAreas[name]
  342.   end
  343.  
  344.   function api.addObject(objectInfo)
  345.     assert(type(objectInfo)=="table","expected table, got "..type(objectInfo))
  346.     objectInfo = fillTable(objectInfo,default.object)
  347.     assert(objects[objectInfo.name]==nil,"an object with the name '"..objectInfo.name.."' already exists")
  348.     objects[objectInfo.name] = objectInfo
  349.   end
  350.  
  351.   function api.drawObject(name)
  352.     assert(objects[name]~=nil,"Object '"..name.."' doesn't exsist")
  353.     local objData = objects[name]
  354.     if objData.visible == false then return end
  355.     assert(objData.states~=nil,"Object '"..name.."' has no states!")
  356.     assert(objData.states[objData.state],"Object '"..name.."' doesn't have state '"..objData.state.."'")
  357.     term.setBackgroundColor(objData.states[objData.state].back)
  358.     term.setTextColor(objData.states[objData.state].text)
  359.     for i = 0, objData.maxY-objData.minY do
  360.       term.setCursorPos(objData.minX,objData.minY+i)
  361.       term.write(string.rep(" ",objData.maxX-objData.minX+1))
  362.     end
  363.     if objData.text then
  364.       local xPos = objData.minX+math.floor(((objData.maxX-objData.minX+1)-#objData.text)/2)
  365.       local yPos = objData.minY+(objData.maxY-objData.minY)/2
  366.       term.setCursorPos(xPos,yPos) term.write(objData.text)
  367.     end  
  368.   end
  369.  
  370.   function api.toggleObjectState(name) -- Only works if an object has two states
  371.     assert(objects[name]~=nil,"Object '"..name.."' doesn't exist")
  372.     assert(countIndexes(objects[name].states)==2,"Object '"..name.."' can't be toggled, it doesn't have two states")
  373.     curState = objects[name].state
  374.     for a,b in pairs(objects[name].states) do
  375.       if a ~= curState then
  376.         objects[name].state = a
  377.       end
  378.     end
  379.     return objects[name].state
  380.   end
  381.  
  382.   function api.setObjectState(name,state)
  383.     assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist")
  384.     assert(objects[name].states[state],"Object '"..name.."' doesn't have state '"..state.."'")
  385.     objects[name].state = state
  386.   end
  387.  
  388.   function api.getObject(name)
  389.     assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist")
  390.     return objects[name]
  391.   end
  392.  
  393.   function api.toggleObjectVisible(name)
  394.     assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist")
  395.     objects[name].visible = not objects[name].visible
  396.     return objects[name].visible
  397.   end
  398.  
  399.   function api.toggleObjectClickable(name)
  400.     assert(objects[name] ~= nil,"Object '"..name.."' doesn't exist")
  401.     objects[name].clickable = not objects[name].clickable
  402.     return objects[name].clickable
  403.   end
  404.  
  405.   return api
  406. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement