Guest User

Texter.lua

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

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×