Guest User

Texter

a guest
Jan 27th, 2013
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- version: Unspeakable Crawling Rachis
  2.  
  3. Texter = {}
  4. Texter._LastInputStr  = ""
  5. Texter._LastInputArgs = "1, 3"
  6. Texter._LastInputFont = "7px"
  7. Texter._Fonts = {}
  8.  
  9. ------------------ User config zone -------------------
  10. Texter.FONT_FOLDERS_TO_LOAD = {"TexterFonts", "Scripts", "%."}   -- All file will be "dofile" under this foler name, plus the root dir (in regex form %.)
  11. Texter.DISPLAY_MESSAGES     = true              -- Should show the startup message
  12. Texter.FONT_SEARCH_DEPTH    = 3                 -- How deep should texter search the font folder
  13. ---------------- User config zone ends ----------------
  14.  
  15. function Texter.Init(register)
  16.     Texter._Fontmatrix = {}
  17.     Texter._Fonts = {}
  18.     -- Please don't let Texter too far away from font file :)
  19.     local fontFiles = Texter.LoadAllFontsInFolder(".", Texter.FONT_FOLDERS_TO_LOAD, Texter.FONT_SEARCH_DEPTH)
  20.     local msg = ""
  21.     if(Texter._Fontmatrix ~= nil) then
  22.         for fontName in pairs(Texter._Fontmatrix) do
  23.             table.insert(Texter._Fonts, fontName)
  24.         end
  25.         msg = "Texter: "..#fontFiles.." font file(s) loaded, "..#Texter._Fonts.." font(s) available in total."
  26.     else
  27.         msg = "Texter: No font found."
  28.     end
  29.     if( Texter.DISPLAY_MESSAGES ) then
  30.         tpt.log(msg)
  31.     end
  32.     if( register == nil or register == true ) then
  33.         tpt.register_keypress(Texter._HotkeyHandler)
  34.     end
  35. end
  36.  
  37. -- Internal methods
  38. function Texter._IsFolder(path)
  39.     local _isFolder = false
  40.     if(path ~= nil) then
  41.         -- API bug, not fixed right now (ver 85.0)
  42.         -- if( fs.isDirectory(path)  ) then
  43.                 -- _isFolder = true
  44.         -- end
  45.         if( fs.isDirectory(path) == fs.isDirectory(".") ) then
  46.             _isFolder = true
  47.         end
  48.     end
  49.     return _isFolder
  50. end
  51. function Texter._GetFontHeight(fontName)
  52.     local height = 0
  53.     if( Texter._Fontmatrix ~= nil and Texter._Fontmatrix[fontName] ~=nil and Texter._Fontmatrix[fontName].height ~= nil  ) then
  54.         height = Texter._Fontmatrix[fontName].height
  55.     else
  56.         height = 7 -- 7 is a lucky number
  57.     end
  58.     return height
  59. end
  60. function Texter._Input(eventHandler, fonts, paramsText, strText, fontText)
  61.     local controlHeight = 17
  62.     if( paramsText == nil  ) then paramsText = "" end
  63.     if( strText    == nil  ) then strText    = "" end
  64.     if( fontText   == nil  ) then fontText   = "" end
  65.     if( fonts      == nil  ) then fonts      = {} end
  66.    
  67.     local isContains = function(inTable, value)
  68.         local isContain = false
  69.         for i=1, #inTable do
  70.             if( value == inTable[i]  ) then
  71.                 isContain = true
  72.                 break
  73.             end
  74.         end
  75.         return isContain
  76.     end
  77.    
  78.     local TexterWin = Window:new(-1, -1, 500, 100)
  79.     local paramsBox = Textbox:new(10, 32, 252, controlHeight, paramsText, "ptype, hspc, vspc")
  80.     local paramsLabel = Label:new(11, 9, 232, controlHeight, "Enter the element name you want to use and\nthe spacing between letters (horizontal/vertical).")
  81.     local stringBox = Textbox:new(10, 57, 480, controlHeight, strText, "Input text to create under mouse. Use \\n for new line, \\\\n for \\n. Sorry, you can't get \\\\n.")
  82.     local fontBtn = Button:new(282, 32, 208, controlHeight, "No font available")
  83.     local fontLabel = Label:new(283, 9, 150, controlHeight, "Select the font you want to use.")
  84.     local cancelBtn = Button:new(0, 83, 251, controlHeight, "Cancel")
  85.     cancelBtn:action(function(sender)interface.closeWindow(TexterWin)end)
  86.     local okayBtn = Button:new(250, 83, 250, controlHeight, "Okay")
  87.     okayBtn:action(
  88.         function(sender)
  89.             if( eventHandler ~= nil and type(eventHandler) == "function"  ) then
  90.                 -- Use event because I can't make things like tpt.input
  91.                 eventHandler(paramsBox:text(), stringBox:text(), fontBtn:text())
  92.             end
  93.             interface.closeWindow(TexterWin)
  94.         end
  95.     )
  96.    
  97.     if(#fonts > 0) then
  98.         if( isContains(fonts, fontText)  ) then
  99.             fontBtn:text(fontText)
  100.         else
  101.             fontBtn:text(fonts[1])
  102.         end
  103.         fontBtn:action(
  104.             function(sender)
  105.                 local winX, winY = TexterWin:position()
  106.                 local btnX, btnY = fontBtn:position()
  107.                 local btnW, btnH = fontBtn:size()
  108.                 local listWin = Window:new(winX+btnX, winY+btnY-8*(#fonts-1), btnW, (btnH-1)*#fonts)
  109.                 for i=1, #fonts do
  110.                     local optionBtn = Button:new(0, (btnH-1)*(i-1), btnW, btnH, fonts[i])
  111.                     optionBtn:action(
  112.                         function(sender)
  113.                             interface.closeWindow(listWin)
  114.                             fontBtn:text(optionBtn:text())
  115.                         end
  116.                     )
  117.                     listWin:addComponent(optionBtn)
  118.                 end
  119.                 interface.showWindow(listWin)
  120.             end
  121.         )
  122.     end
  123.    
  124.     TexterWin:addComponent(cancelBtn)
  125.     TexterWin:addComponent(okayBtn)
  126.     TexterWin:addComponent(stringBox)
  127.     TexterWin:addComponent(paramsBox)
  128.     TexterWin:addComponent(paramsLabel)
  129.     TexterWin:addComponent(fontBtn)
  130.     TexterWin:addComponent(fontLabel)
  131.    
  132.     interface.showWindow(TexterWin)
  133. end
  134. function Texter._FindAllFile(rootPath, foldersToLoad, depth)
  135.     if(  rootPath == nil  ) then
  136.         rootPath = "."
  137.     end
  138.     if(  depth == nil  ) then
  139.         depth = 1
  140.     end
  141.     local files = {}
  142.     local isTargetFolder = false
  143.     for i, folderName in ipairs(foldersToLoad) do
  144.         if( string.match(rootPath, "\\?"..folderName.."$") ~= nil ) then
  145.             isTargetFolder = true
  146.             break
  147.         end
  148.     end
  149.     if( isTargetFolder ) then  -- If not the folder we want, ignore it
  150.         files = fs.list(rootPath)
  151.     end
  152.    
  153.     -- Trim match array
  154.     local index = 1 -- Lua fool
  155.     for i=1, #files do
  156.         if( files[index] == "Texter.lua"
  157.           or string.match(files[index], "%.texterfont$") == nil
  158.           or Texter._IsFolder(rootPath.."\\"..files[index]) ) then
  159.             table.remove(files, index)
  160.         else
  161.             files[index] = rootPath.."\\"..files[index] -- full path
  162.             index = index + 1
  163.         end
  164.     end
  165.    
  166.     -- Check subs
  167.     if(  depth > 0  ) then
  168.         local subs = fs.list(rootPath)
  169.         local subFiles = nil
  170.         for i=1, #subs do
  171.             if( Texter._IsFolder(rootPath.."\\"..subs[i]) ) then
  172.                 subFiles = Texter._FindAllFile(rootPath.."\\"..subs[i], foldersToLoad, depth - 1)
  173.                 Texter._AppendArray(files, subFiles)
  174.             end
  175.         end
  176.     end
  177.     return files
  178. end
  179. function Texter._AppendArray(oriArray, arrayToAppend) -- Append an array to the original array
  180.     if(  oriArray~= nil and arrayToAppend ~= nil and #arrayToAppend>0  ) then
  181.         for i=1, #arrayToAppend do
  182.             table.insert(oriArray, arrayToAppend[i])
  183.         end
  184.     end
  185.     return oriArray
  186. end
  187.  
  188. -- Helper methods and handlers
  189. function Texter._HotkeyHandler(key, keyNum, modifier, event) -- Hotkey handler
  190.     if( event==1 and keyNum==116 and modifier==64  ) then -- Ctrl + t
  191.         -- Additional settings
  192.         local ptype = elements[tpt.selectedl]
  193.         if( ptype == nil  ) then
  194.             ptype = 1 --"DUST"
  195.         end
  196.         -- Prompt
  197.         Texter._Input(
  198.             Texter._InputHandler,
  199.             Texter._Fonts,
  200.             elements.property(ptype, "Name")..", "..Texter._LastInputArgs,
  201.             Texter._LastInputStr,
  202.             Texter._LastInputFont
  203.         )
  204.     end
  205. end
  206. function Texter._InputHandler(params, str, fontName) -- Input handler
  207.     local args = {}
  208.     if( string.len(str) > 0  ) then
  209.         Texter._LastInputStr = str
  210.         str = string.gsub(str, "([^\\]?)\\n", "%1\n")  -- Small trick
  211.         str = string.gsub(str, "([^\\]?)\\\\n", "%1\\n")
  212.     end
  213.    
  214.     if( string.len(params) > 0  ) then Texter._LastInputArgs = string.gsub(params, "%s*%w*%s*,%s*(.*)", "%1") end
  215.     local i=1
  216.     for arg in string.gmatch(params, "%s*(%w*)%s*,?") do
  217.         args[i] = arg
  218.         i = i+1
  219.     end
  220.     Texter._LastInputFont = fontName
  221.    
  222.     if( pcall(tpt.element, args[1]) == false  ) then
  223.         args[1] = "DUST"
  224.     end
  225.     Texter.Tstr(str, tpt.mousex, tpt.mousey, args[1], args[2], args[3], fontName)
  226. end
  227.  
  228. -- APIs
  229. function Texter.LoadAllFontsInFolder(rootPath, foldersToLoad, depth) -- Load all fonts in target folder(s)
  230.     local fonts = Texter._FindAllFile(rootPath, foldersToLoad, depth)
  231.     if(  fonts ~= nil  ) then
  232.         for i=1, #fonts do
  233.             dofile(fonts[i])
  234.         end
  235.     end
  236.     return fonts
  237. end
  238. function Texter.Tchar(char, x, y, ptype, fontName) -- Draw a single character
  239.     local mtx     = {}
  240.     local letter  = {}
  241.     local margin_L = 0 -- margin left
  242.     local margin_R = 0 -- margin right
  243.     local margin_T = 0 -- margin top
  244.     -- if given font not available, use the first available one
  245.     if( fontName == nil or Texter._Fontmatrix[fontName] == nil  ) then
  246.         for font in pairs(Texter._Fontmatrix) do
  247.             fontName = font
  248.             break
  249.         end
  250.     end
  251.     -- if still not available, break
  252.     if( fontName == nil  ) then return 0 end
  253.    
  254.     -- get character data
  255.     letter = Texter._Fontmatrix[fontName][char]
  256.     if( letter == nil  ) then
  257.         letter = Texter._Fontmatrix[fontName]["nil"]
  258.     end
  259.     if( letter == nil  ) then return 0 end -- ["nil"] not defined
  260.     mtx = letter.Mtx
  261.     if( letter.Margin ~= nil  ) then
  262.         if(letter.Margin.Left  ~= nil)then margin_L = letter.Margin.Left  end
  263.         if(letter.Margin.Right ~= nil)then margin_R = letter.Margin.Right end
  264.         if(letter.Margin.Top   ~= nil)then margin_T = letter.Margin.Top   end
  265.     end
  266.    
  267.     local width  = 0
  268.     for i=1, #mtx do --mtx height
  269.         if(#mtx[i] > width)then width = #mtx[i] end
  270.         for j=1, width do
  271.             if( mtx[i][j]~=0  ) then --TODO: other ptype support
  272.                 pcall(tpt.create, x+j-1+margin_L, y+i-1+margin_T, ptype)
  273.             end
  274.         end
  275.     end
  276.     if(width > 0)then
  277.         width = width + margin_L + margin_R
  278.     end
  279.     return width
  280. end
  281. function Texter.Tstr(str, x, y, ptype, hspacing, vspacing, fontName) -- Draw a string
  282.     local ox    = 0
  283.     local oy    = 0
  284.     local oy    = 0
  285.     local fontH = Texter._GetFontHeight(fontName)
  286.     if( hspacing == nil  ) then
  287.         hspacing = 1
  288.     end
  289.     if( vspacing == nil  ) then
  290.         vspacing = 3
  291.     end
  292.     for i=1,string.len(str) do
  293.         if( string.sub(str, i, i) == "\n"  ) then
  294.             oy = vspacing + oy + fontH
  295.             ox = 0
  296.         else
  297.             ox = hspacing + ox + Texter.Tchar(string.sub(str, i, i), x+ox, y+oy, ptype, fontName)
  298.         end
  299.     end
  300.     return string.len(str)
  301. end
  302. function T(str, ptype, hspc, vspc, fontName) -- Shortcut for better user experience
  303.     if( ptype == nil  ) then
  304.         ptype = elements[tpt.selectedl] -- elements.property(tpt.selectedl, "Name")
  305.     end
  306.     if( str == nil  ) then str = "" end
  307.     if( ptype == nil  ) then
  308.         ptype = "DUST"
  309.     end
  310.     Texter.Tstr(str, tpt.mousex, tpt.mousey, ptype, hspc, vspc, fontName)
  311.     return string.len(str)
  312. end
  313.  
  314. Texter.Init()
Advertisement
Add Comment
Please, Sign In to add comment