Guest User

TFGen

a guest
Jan 27th, 2013
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 33.16 KB | None | 0 0
  1. -- Font Generator for Texter
  2. -- Version 0.1.0
  3.  
  4. TFGen = {}
  5. TFGen.MAIN_WIDTH = 611
  6. TFGen.MAIN_HEIGHT = 383
  7. TFGen.ShowSelectRect = false
  8. TFGen.Drawing = {
  9.     W = 0,
  10.     H = 0,
  11.     StartX = 0,
  12.     StartY = 0,
  13.     Scrolled = 0,
  14.     Modifier = 0
  15. }
  16. TFGen.UIItems = {
  17.     -- { --example
  18.         -- Type    = "fill",
  19.         -- Pos     = {X=1, Y=1, W=1, H=1}, --X,Y,X2,Y2 for line
  20.         -- Color   = {R=255, G=255, B=255, A=125},
  21.         -- Life    = 555  --  -1:forever X:stop render after X frames
  22.         -- Fadeout = {From=255, T=30}  --  fadeout(alpha), "to" is always 0
  23.     -- }
  24. }
  25. TFGen.GlyphCells = {} --structure { {X,Y,W,H} }
  26. TFGen.Glyph      = {} -- structure: {Height, {Mtx, Pos={X, Y, W, H}, Margin={Left, Right, Top}}}
  27. function TFGen.Init(register)
  28.     if( register == nil or register == true ) then
  29.         tpt.register_keypress(TFGen._HotkeyHandler)
  30.     end
  31. end
  32.  
  33. -- Event handlers
  34. function TFGen._HotkeyHandler(key, keyNum, modifier, event)
  35.     if( event==1 ) then -- Modifier record for click event
  36.         if( keyNum == 304 and modifier == 0 ) then TFGen.Drawing.Modifier = 1   end -- shift
  37.         if( keyNum == 306 and modifier == 0 ) then TFGen.Drawing.Modifier = 64  end -- ctrl
  38.         if( keyNum == 308 and modifier == 0 ) then TFGen.Drawing.Modifier = 256 end -- alt
  39.     end
  40.     if( event==2 ) then -- Modifier record for click event
  41.         TFGen.Drawing.Modifier = 0
  42.     end
  43.     if( event==1 and keyNum==116 and modifier==65 ) then -- Ctrl + Shift + t, start
  44.         TFGen.Drawing.StartX = tpt.mousex
  45.         TFGen.Drawing.StartY = tpt.mousey
  46.         TFGen.Drawing.StartY = tpt.mousey
  47.         tpt.set_pause(1)
  48.         local notRunning = pcall( tpt.register_step, TFGen._StepHandler )
  49.         pcall( tpt.register_keypress   , TFGen._KeypressHandler)
  50.         pcall( tpt.register_mouseclick , TFGen._ClickHandler   )
  51.         table.insert(
  52.             TFGen.UIItems,
  53.             {
  54.                 Type  = "text",
  55.                 Text  = "Select an area to place glyph rectangle.\nLeft click to place, right click to undo.\nEnter to submit, space to cancle.",
  56.                 Pos   = {X=205, Y=190},
  57.                 Color = {R=255, G=255, B=25, A=255},
  58.                 Life  = 180,
  59.                 Fadeout = {From=255, T=60}
  60.             }
  61.         )
  62.         if( notRunning ) then
  63.             table.insert(
  64.                 TFGen.UIItems,
  65.                 {
  66.                     Type  = "text",
  67.                     Text  = "Font Generator for Texter is Running...",
  68.                     Pos   = {X=425, Y=365},
  69.                     Color = {R=255, G=255, B=25, A=155},
  70.                     Life  = -1,
  71.                 }
  72.             )
  73.         end
  74.     end
  75. end
  76. function TFGen._KeypressHandler(key, keyNum, modifier, event)
  77.     if( event==2 and keyNum==13 and modifier==0 and TFGen.Glyph[1] == nil) then   -- Enter submit glyph choice, do not respose when editing
  78.         pcall(tpt.unregister_mouseclick, TFGen._ClickHandler)
  79.         pcall(tpt.unregister_keypress,   TFGen._KeypressHandler)
  80.         TFGen.ShowSelectRect = false
  81.         TFGen.Glyph = TFGen._GlyphGen(TFGen.GlyphCells)
  82.         TFGen.GlyphCells = {}
  83.         TFGen.Editor.Init()
  84.         TFGen.Editor.Show(true)
  85.     end
  86.     if( event==2 and keyNum==32 and modifier==0 ) then   -- Space cancle all
  87.         TFGen.Reset()
  88.     end
  89. end
  90. function TFGen._ClickHandler(x, y, button, event, scroll) -- button: 0 scroll, 1 left, 2 mid, 4 right; scroll: -1 down, 1 up
  91.     if( button == 1 and event == 3) then -- Resize rectangle
  92.         if( TFGen.Drawing.Modifier == 0 ) then -- none
  93.             TFGen.Drawing.W = x - TFGen.Drawing.StartX
  94.             TFGen.Drawing.H = y - TFGen.Drawing.StartY
  95.             if(x > TFGen.MAIN_WIDTH )then TFGen.Drawing.W = TFGen.MAIN_WIDTH  - TFGen.Drawing.StartX end
  96.             if(y > TFGen.MAIN_HEIGHT)then TFGen.Drawing.H = TFGen.MAIN_HEIGHT - TFGen.Drawing.StartY end
  97.         end
  98.         return false
  99.     end
  100.     if( button == 1 and event == 1) then -- Start draw add rectangle
  101.         if( TFGen.Drawing.Modifier == 0 ) then -- none
  102.             if(x > TFGen.MAIN_WIDTH )then x = TFGen.MAIN_WIDTH  end
  103.             if(y > TFGen.MAIN_HEIGHT)then y = TFGen.MAIN_HEIGHT end
  104.             TFGen.Drawing.StartX = x
  105.             TFGen.Drawing.StartY = y
  106.             TFGen.ShowSelectRect = true
  107.         end
  108.         return false
  109.     end
  110.     if( button == 1 and event == 2) then -- Add rectangle
  111.         if( TFGen.Drawing.Modifier == 0 ) then -- none
  112.             TFGen.ShowSelectRect = false
  113.             if(TFGen.Drawing.W < 0)then
  114.                 TFGen.Drawing.W = -1*TFGen.Drawing.W
  115.                 TFGen.Drawing.StartX = TFGen.Drawing.StartX - TFGen.Drawing.W
  116.             end
  117.             if(TFGen.Drawing.H < 0)then
  118.                 TFGen.Drawing.H = -1*TFGen.Drawing.H
  119.                 TFGen.Drawing.StartY = TFGen.Drawing.StartY - TFGen.Drawing.H
  120.             end
  121.             if(TFGen.Drawing.W > 0 and TFGen.Drawing.H > 0)then
  122.                 table.insert(
  123.                     TFGen.GlyphCells,
  124.                     {
  125.                         X = TFGen.Drawing.StartX,
  126.                         Y = TFGen.Drawing.StartY,
  127.                         W = TFGen.Drawing.W,
  128.                         H = TFGen.Drawing.H
  129.                     }
  130.                 )
  131.             end
  132.         end
  133.         return false
  134.     end
  135.     if( button == 4 and event == 1) then -- Undo
  136.         table.remove(TFGen.GlyphCells)
  137.         return false
  138.     end
  139. end
  140. function TFGen._StepHandler()
  141.     TFGen._DrawSelectRect(TFGen.Drawing.StartX, TFGen.Drawing.StartY, TFGen.Drawing.W, TFGen.Drawing.H)
  142.     TFGen._DrawGUI()
  143. end
  144. function TFGen._DrawGUI()
  145.     for i, glyph in pairs(TFGen.GlyphCells) do
  146.         tpt.drawrect(glyph.X, glyph.Y, glyph.W, glyph.H, 255, 255, 255, 125)
  147.     end
  148.     for i, glyph in pairs(TFGen.Glyph) do
  149.         if(type(glyph) == "table") then
  150.             local m = {}
  151.             local color = {}
  152.             if( glyph.Margin == nil ) then
  153.                 m.top   = 0
  154.                 m.left  = 0
  155.                 m.right = 0
  156.             else
  157.                 if( glyph.Margin.Top   == nil ) then m.top   = 0 else m.top   =  glyph.Margin.Top   end
  158.                 if( glyph.Margin.Left  == nil ) then m.left  = 0 else m.left  =  glyph.Margin.Left  end
  159.                 if( glyph.Margin.Right == nil ) then m.right = 0 else m.right =  glyph.Margin.Right end
  160.             end
  161.             if( i == TFGen.CurrentGlyphIndex )then
  162.                 color = {R=55 , G=255, B=55 , A=125}
  163.             else
  164.                 color = {R=255, G=255, B=125, A=125}
  165.             end
  166.             pcall(
  167.                 tpt.drawrect,
  168.                 glyph.Pos.X - m.left,
  169.                 glyph.Pos.Y - m.top ,
  170.                 glyph.Pos.W + m.left + m.right,
  171.                 TFGen.Glyph.Height, -- No matter what glyph.Pos.H is
  172.                 color.R, color.G, color.B, color.A
  173.             )
  174.             local char = glyph.Char
  175.             if( char ~= nil) then
  176.                 if( char == " " ) then char = "space" end -- Special
  177.                 pcall(
  178.                     tpt.drawtext,
  179.                     glyph.Pos.X - m.left,
  180.                     glyph.Pos.Y - m.top - 10, -- Default font height + 3?
  181.                     i..":"..char,
  182.                     color.R, color.G, color.B, color.A
  183.                 )
  184.             end
  185.         end
  186.     end
  187.     for i, item  in pairs(TFGen.UIItems) do
  188.         --Few types, so if-else-if won't be performance critical
  189.         if item.Pos      == nil then item.Pos     = {X=1, Y=1, X2=1, Y2=1, W=1, H=1} end
  190.         if item.Color    == nil then item.Color   = {R=255, G=255, B=255, A=125} end
  191.         if item.Fadeout  == nil then item.Fadeout = {From = 255, T=0}  end
  192.         if item.Life     == nil then item.Life    = 60 end
  193.         if item.Text     == nil then item.Text    = "" end
  194.        
  195.         if(item.Life > 0 or item.Life == -1) then
  196.             if(item.Life > 0)then item.Life = item.Life - 1 end
  197.             --fadeout, no fadeout for forever ones
  198.             if(item.Life <= item.Fadeout.T and item.Life ~= -1)then
  199.                 item.Color.A = item.Fadeout.From * item.Life/item.Fadeout.T
  200.             end
  201.             if(item.Type == "text") then
  202.                 tpt.drawtext(item.Pos.X, item.Pos.Y, item.Text, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  203.             elseif (item.Type == "pixel") then
  204.                 tpt.drawpixel(item.Pos.X, item.Pos.Y, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  205.             elseif (item.Type == "line") then
  206.                 tpt.drawline(item.Pos.X, item.Pos.Y, item.Pos.X2, item.Pos.Y2, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  207.             elseif (item.Type == "rect") then
  208.                 tpt.drawrect(item.Pos.X, item.Pos.Y, item.Pos.W, item.Pos.H, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  209.             elseif (item.Type == "fill" ) then
  210.                 tpt.fillrect(item.Pos.X, item.Pos.Y, item.Pos.W, item.Pos.H, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  211.             end
  212.         else -- You were dead
  213.             table.remove(TFGen.UIItems, i)
  214.             i = i-1 --Lua will shifting down other elements to close the space, so we might jump one item off without this
  215.         end
  216.     end
  217. end
  218. function TFGen._DrawSelectRect(posX, posY, width, height)
  219.     if(width < 0)then
  220.         width = -1*width
  221.         posX = posX - width
  222.     end
  223.     if(height < 0)then
  224.         height = -1*height
  225.         posY = posY - height
  226.     end
  227.     if(TFGen.ShowSelectRect)then
  228.         tpt.drawrect(posX, posY, width, height, 255, 255, 255, 125)
  229.     end
  230. end
  231.  
  232. -- Generate glyph
  233. function TFGen._GlyphGen(glyphCells)
  234.     local glyphList  = {}
  235.     glyphList.Name   = "font1"
  236.     glyphList.Height = -1
  237.     for index, glyph in pairs(glyphCells) do
  238.         -- Minimum Bound Box detection, using the simplest methods, O(n^2)
  239.         local mbb = {}
  240.         for i = 1, glyph.W do
  241.             for j = 1, glyph.H do
  242.                 if(tpt.get_property("type", glyph.X + i, glyph.Y + j) ~= 0)then
  243.                     if(mbb.left   == nil                             )then mbb.left   = glyph.X + i end --the fisrt non-empty column
  244.                     if(mbb.right  == nil or mbb.right  ~= glyph.X + i)then mbb.right  = glyph.X + i end --the last non-empty column
  245.                     if(mbb.top    == nil or mbb.top    >  glyph.Y + j)then mbb.top    = glyph.Y + j end --the smallest non-empty row
  246.                     if(mbb.bottom == nil or mbb.bottom <  glyph.Y + j)then mbb.bottom = glyph.Y + j end --the biggest non-empty row
  247.                 end
  248.             end
  249.         end
  250.         if(mbb.left ~= nil and mbb.right ~= nil and mbb.top ~= nil and mbb.bottom ~= nil) then
  251.             local glyphArea = {X=mbb.left, Y=mbb.top, W=(mbb.right - mbb.left), H=(mbb.bottom - mbb.top)}
  252.             local mtx       = TFGen._DigitizeArea(glyphArea)
  253.             if( (mbb.bottom - mbb.top) > glyphList.Height) then
  254.                 glyphList.Height = mbb.bottom - mbb.top
  255.             end
  256.             table.insert(
  257.                 glyphList,
  258.                 {
  259.                     Char   = "",
  260.                     Mtx    = mtx,
  261.                     Pos    = glyphArea,
  262.                     Margin = {Top=0, Left=0, Right=0}
  263.                 }
  264.             )
  265.         end
  266.     end
  267.     return glyphList
  268. end
  269. -- Digitize selected area
  270. function TFGen._DigitizeArea(area)
  271.     local mtx = {}
  272.     local x1 = area.X
  273.     local x2 = area.X + area.W
  274.     local y1 = area.Y
  275.     local y2 = area.Y + area.H
  276.    
  277.     if(area ~= nil and area.X ~= nil and area.Y ~= nil and area.W ~= nil and area.H ~= nil)then
  278.         for y = y1, y2 do
  279.             local row = {}
  280.             for x = x1, x2 do
  281.                 local isSucceed, ptype = pcall(tpt.get_property, "type", x, y)
  282.                 if(isSucceed)then
  283.                     table.insert(row, ptype)
  284.                 else
  285.                     table.insert(row, 0)
  286.                 end
  287.             end
  288.             table.insert(mtx, row)
  289.         end
  290.     end
  291.     return mtx
  292. end
  293. -- Reset
  294. function TFGen.Reset()
  295.     pcall(tpt.unregister_step,       TFGen._StepHandler)
  296.     pcall(tpt.unregister_keypress,   TFGen._KeypressHandler)
  297.     pcall(tpt.unregister_mouseclick, TFGen._ClickHandler)
  298.     TFGen.ShowSelectRect = false
  299.     TFGen.GlyphCells = {}
  300.     TFGen.Glyph = {}
  301.     TFGen.UIItems = {}
  302. end
  303.  
  304.  
  305. -- The glyph editor after font generation
  306. TFGen.Editor = {}
  307. TFGen.Editor.Cons = {} -- Controls table
  308. TFGen.Editor.Pos  = {X=100, Y=100}
  309. TFGen.Editor.Visable = true
  310. TFGen.CurrentGlyphIndex = -1
  311. function TFGen.Editor.Init()
  312.     -- If no glyph generated, quit
  313.     if(TFGen.Glyph.Height == nil or TFGen.Glyph[1] == nil)then
  314.         TFGen.Reset()
  315.         TFGen.Editor.Reset()
  316.         return false
  317.     end
  318.     tpt.register_keypress(TFGen.Editor._KeypressHandler)
  319.     tpt.register_mouseclick(TFGen.Editor._ClickHandler)
  320.     TFGen.CurrentGlyphIndex = 1
  321.     local controlHeight = 14
  322.     -- Position to show
  323.     local properPos = TFGen.Editor.GetClosePos(TFGen.Glyph[TFGen.CurrentGlyphIndex])
  324.     TFGen.Editor.Pos.X = properPos.X
  325.     TFGen.Editor.Pos.Y = properPos.Y
  326.     local editorX = properPos.X
  327.     local editorY = properPos.Y
  328.     local editorW = 144
  329.    
  330.     local lines = 0    -- 1st line : 0
  331.     local prevBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Prev"                       )
  332.     local nextBtn      = Button:new( editorX + editorW/2  , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Next"                       )
  333.     lines = lines + 2  -- 2nd line : 2
  334.     local nameBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Name: "..TFGen.Glyph.Name   )
  335.     lines = lines + 1  -- 3rd line : 3
  336.     local charBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Char: []"                   )
  337.     lines = lines + 1  -- 4th line : 4
  338.     local autoCharBtn  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Auto assign"                )
  339.     lines = lines + 1  -- 5th line : 5
  340.     local heightLabel  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Font Height"                )
  341.     local heightDecBtn = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  342.     local heightBtn    = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  tostring(TFGen.Glyph.Height) )
  343.     local heightIncBtn = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  344.     lines = lines + 1  -- 6th line : 6
  345.     local mTopLabel    = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Top"                 )
  346.     local mTopDecBtn   = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  347.     local mTopBtn      = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  348.     local mTopIncBtn   = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  349.     lines = lines + 1  -- 7th line : 7
  350.     local mLeftLabel   = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Left"                )
  351.     local mLeftDecBtn  = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  352.     local mLeftBtn     = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  353.     local mLeftIncBtn  = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  354.     lines = lines + 1  -- 8th line : 8
  355.     local mRightLabel  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Right"               )
  356.     local mRightDecBtn = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  357.     local mRightBtn    = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  358.     local mRightIncBtn = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  359.     lines = lines + 1  -- 9th line : 9
  360.     local deleteBtn    = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Delete this glyph (No undo)")
  361.     lines = lines + 1  -- 10th line : 10
  362.     local cancelAllBtn = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Cancel All"                 )
  363.     local submitAllBtn = Button:new( editorX + editorW/2  , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Submit All"                 )
  364.    
  365.     prevBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Prev"      ,    sender) end )
  366.     nextBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Next"      ,    sender) end )
  367.     nameBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Name"      ,    sender) end )
  368.     charBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Char"      ,    sender) end )
  369.     autoCharBtn :action ( function(sender) TFGen.Editor.CommandHandler("AutoAssign",    sender) end )
  370.     heightDecBtn:action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  371.     heightBtn   :action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  372.     heightIncBtn:action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  373.     mTopDecBtn  :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  374.     mTopBtn     :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  375.     mTopIncBtn  :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  376.     mLeftDecBtn :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  377.     mLeftBtn    :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  378.     mLeftIncBtn :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  379.     mRightDecBtn:action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  380.     mRightBtn   :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  381.     mRightIncBtn:action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  382.     deleteBtn   :action ( function(sender) TFGen.Editor.CommandHandler("Delete"    ,    sender) end )
  383.     cancelAllBtn:action ( function(sender) TFGen.Editor.CommandHandler("CancelAll" ,    sender) end )
  384.     submitAllBtn:action ( function(sender) TFGen.Editor.CommandHandler("SubmitAll" ,    sender) end )
  385.    
  386.     TFGen.Editor.Cons.prevBtn      = prevBtn
  387.     TFGen.Editor.Cons.nextBtn      = nextBtn
  388.     TFGen.Editor.Cons.nameBtn      = nameBtn
  389.     TFGen.Editor.Cons.charBtn      = charBtn
  390.     TFGen.Editor.Cons.autoCharBtn  = autoCharBtn
  391.     TFGen.Editor.Cons.heightLabel  = heightLabel
  392.     TFGen.Editor.Cons.heightDecBtn = heightDecBtn
  393.     TFGen.Editor.Cons.heightBtn    = heightBtn
  394.     TFGen.Editor.Cons.heightIncBtn = heightIncBtn
  395.     TFGen.Editor.Cons.mTopLabel    = mTopLabel
  396.     TFGen.Editor.Cons.mTopDecBtn   = mTopDecBtn
  397.     TFGen.Editor.Cons.mTopBtn      = mTopBtn
  398.     TFGen.Editor.Cons.mTopIncBtn   = mTopIncBtn
  399.     TFGen.Editor.Cons.mLeftLabel   = mLeftLabel
  400.     TFGen.Editor.Cons.mLeftDecBtn  = mLeftDecBtn
  401.     TFGen.Editor.Cons.mLeftBtn     = mLeftBtn
  402.     TFGen.Editor.Cons.mLeftIncBtn  = mLeftIncBtn
  403.     TFGen.Editor.Cons.mRightLabel  = mRightLabel
  404.     TFGen.Editor.Cons.mRightDecBtn = mRightDecBtn
  405.     TFGen.Editor.Cons.mRightBtn    = mRightBtn
  406.     TFGen.Editor.Cons.mRightIncBtn = mRightIncBtn
  407.     TFGen.Editor.Cons.cancelAllBtn = cancelAllBtn
  408.     TFGen.Editor.Cons.submitAllBtn = submitAllBtn
  409.     TFGen.Editor.Cons.deleteBtn    = deleteBtn
  410.    
  411.     interface.addComponent(heightLabel )
  412.     interface.addComponent(mTopLabel   )
  413.     interface.addComponent(mLeftLabel  )
  414.     interface.addComponent(mRightLabel )
  415.    
  416.     interface.addComponent(prevBtn     )
  417.     interface.addComponent(nextBtn     )
  418.     interface.addComponent(nameBtn     )
  419.     interface.addComponent(charBtn     )
  420.     interface.addComponent(autoCharBtn )
  421.     interface.addComponent(heightDecBtn)
  422.     interface.addComponent(heightBtn   )
  423.     interface.addComponent(heightIncBtn)
  424.     interface.addComponent(mTopDecBtn  )
  425.     interface.addComponent(mTopBtn     )
  426.     interface.addComponent(mTopIncBtn  )
  427.     interface.addComponent(mLeftDecBtn )
  428.     interface.addComponent(mLeftBtn    )
  429.     interface.addComponent(mLeftIncBtn )
  430.     interface.addComponent(mRightDecBtn)
  431.     interface.addComponent(mRightBtn   )
  432.     interface.addComponent(mRightIncBtn)
  433.     interface.addComponent(deleteBtn   )
  434.     interface.addComponent(cancelAllBtn)
  435.     interface.addComponent(submitAllBtn)
  436. end
  437.  
  438. -- Command handler
  439. function TFGen.Editor.CommandHandler(command, sender)
  440.     if(pcall(TFGen.Editor.Commands[command], sender) == false) then
  441.         tpt.log("TFGen: Command \""..command.."\"is broken or undefined.")
  442.     end
  443. end
  444. -- Commands
  445. TFGen.Editor.Commands = {}
  446. function TFGen.Editor.Commands.CancelAll()
  447.     TFGen.Reset()
  448.     TFGen.Editor.Reset()
  449. end
  450. function TFGen.Editor.Commands.SubmitAll()
  451.     if( TFGen.Glyph ~= nil ) then
  452.         TFGen.Editor.SaveFontToFile(TFGen.Glyph)
  453.     else
  454.         tpt.message_box("Font not saved", "No glyph found, no font saved, human.")
  455.     end
  456.     TFGen.Reset()
  457.     TFGen.Editor.Reset()
  458. end
  459. function TFGen.Editor.Commands.Prev()
  460.     TFGen.Editor.ChangeIndex(-1, true)
  461.     TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  462. end
  463. function TFGen.Editor.Commands.Next()
  464.     TFGen.Editor.ChangeIndex(1, true)
  465.     TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  466. end
  467. function TFGen.Editor.Commands.Name(sender)
  468.     local input = tpt.input("Font name", "Set the name for your font", TFGen.Glyph.Name)
  469.     if(string.len(input)>0)then
  470.         input = string.gsub(input, "[^%l%u%d_]*", "")
  471.         input = string.gsub(input, "^%d+", "")
  472.         TFGen.Glyph.Name = input
  473.         sender:text("Name: "..TFGen.Glyph.Name)
  474.     end
  475. end
  476. function TFGen.Editor.Commands.Char(sender)
  477.     local currentGlyph = TFGen.Glyph[TFGen.CurrentGlyphIndex]
  478.     local input = tpt.input("Assign the character", "Assign the character for this glyph", currentGlyph.Char)
  479.     if(string.len(input)>0)then
  480.         currentGlyph.Char = string.sub(input, 1, 1)
  481.         sender:text("Char: [ "..currentGlyph.Char.." ]")
  482.     else
  483.         currentGlyph.Char = ""
  484.         sender:text("Char: []")
  485.     end
  486. end
  487. function TFGen.Editor.Commands.AutoAssign() --auto assign characters with given sequence: 0~9, A~Z, a~z, *space*`-=[]\;',./~!@#$%^&*()_+{}|:"<>? (all symbols then shift-symbols)
  488.     local input = tpt.input("Auto assign", "Auto assign characters in order:\n0~9, A~Z, a~z, *space*`-=[]\\;',./~!@#$%^&*()_+{}|:\"<>?\nContinue?\nType 15 for all, 1 for 0~9 only, 2 for upper chars, 4 for lower, 8 for symbols. You can add them up.", "15", "Any input out of 0~15 will be ignored")
  489.     input = tonumber(input)
  490.     if( input ~= nil and input >= 0 and input < 16 ) then
  491.         -- Auto assign in sequence
  492.         local index = 1
  493.         local glyphCount = #TFGen.Glyph
  494.         -- 0~9
  495.         if( bit.band(input, 1) == 1 ) then
  496.             for i = 0, 9 do
  497.                 if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  498.                     TFGen.Glyph[index].Char = string.char( 48 + i )
  499.                     index = index + 1
  500.                 end
  501.             end
  502.         end
  503.         -- Upper chars
  504.         if( bit.band(input, 2) == 2 ) then
  505.             for i = 0, 25 do
  506.                 if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  507.                     TFGen.Glyph[index].Char = string.char( 65 + i )
  508.                     index = index + 1
  509.                 end
  510.             end
  511.         end
  512.         -- Lower chars
  513.         if( bit.band(input, 4) == 4 ) then
  514.             for i = 0, 25 do
  515.                 if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  516.                     TFGen.Glyph[index].Char = string.char( 97 + i )
  517.                     index = index + 1
  518.                 end
  519.             end
  520.         end
  521.         -- Symbols, ordered in logic sequence to deliver better experience for font creators
  522.         if( bit.band(input, 8) == 8) then
  523.             local symbolMap = {" ", "`", "-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "{", "}", "|", ":", "\"", "<", ">", "?"}
  524.             for i = 1, 33 do -- All symbols count: 1 + 32
  525.                 if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  526.                     TFGen.Glyph[index].Char = symbolMap[ i ]
  527.                     index = index + 1
  528.                 end
  529.             end
  530.         end
  531.         -- Clear the rest
  532.         if( index < #TFGen.Glyph ) then
  533.             for i = index, #TFGen.Glyph do
  534.                 TFGen.Glyph[index].Char = ""
  535.                 index = index + 1
  536.             end
  537.         end
  538.         TFGen.Editor.UpdateUI()
  539.     end
  540. end
  541. function TFGen.Editor.Commands.Delete()
  542.     table.remove(TFGen.Glyph, TFGen.CurrentGlyphIndex)
  543.     if(#TFGen.Glyph < 1) then -- No one left
  544.         TFGen.Reset()
  545.         TFGen.Editor.Reset()
  546.     elseif(TFGen.Glyph[TFGen.CurrentGlyphIndex] == nil) then -- We just kill the last one
  547.         TFGen.Editor.ChangeIndex(-1, true)
  548.         TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  549.     end
  550. end
  551. function TFGen.Editor.Commands.HeightMod(sender)
  552.     local opt = sender:text()
  553.     local optList = { ["+"]=1, ["-"]=-1 }
  554.     if(opt == "+" or opt == "-")then -- Increase/Decrease btn
  555.         TFGen.Glyph.Height = TFGen.Glyph.Height + optList[opt]
  556.         TFGen.Editor.Cons.heightBtn:text(tostring(TFGen.Glyph.Height))
  557.     else --Height box
  558.         local input = tpt.input("Set font height", "Set the font height for all glyph (1~"..TFGen.MAIN_HEIGHT..")", tostring(TFGen.Glyph.Height))
  559.         if(string.len(input)>0)then
  560.             local h = tonumber(input)
  561.             if(h ~= nil and h > 0 and h <= TFGen.MAIN_HEIGHT)then
  562.                 TFGen.Glyph.Height = h
  563.                 sender:text(tostring(TFGen.Glyph.Height))
  564.             end
  565.         end
  566.     end
  567. end
  568. function TFGen.Editor.Commands.MarginMod(sender)
  569.     local opt = sender:text()
  570.     local optList = { ["+"]=1, ["-"]=-1 }
  571.     local currentGlyphMargin = TFGen.Glyph[TFGen.CurrentGlyphIndex].Margin
  572.     local marginType = ""
  573.     local maxVal = 0
  574.     if(     sender == TFGen.Editor.Cons.mTopDecBtn   or sender == TFGen.Editor.Cons.mTopIncBtn   or sender == TFGen.Editor.Cons.mTopBtn  )then
  575.         marginType = "Top"
  576.         maxVal = TFGen.MAIN_HEIGHT - 1
  577.     elseif( sender == TFGen.Editor.Cons.mLeftDecBtn  or sender == TFGen.Editor.Cons.mLeftIncBtn  or sender == TFGen.Editor.Cons.mLeftBtn )then
  578.         marginType = "Left"
  579.         maxVal = TFGen.MAIN_WIDTH - 1
  580.     elseif( sender == TFGen.Editor.Cons.mRightDecBtn or sender == TFGen.Editor.Cons.mRightIncBtn or sender == TFGen.Editor.Cons.mRightBtn)then
  581.         marginType = "Right"
  582.         maxVal = TFGen.MAIN_WIDTH - 1
  583.     end
  584.     if(opt == "+" or opt == "-")then -- Increase/Decrease btn
  585.         currentGlyphMargin[marginType] = currentGlyphMargin[marginType] + optList[opt]
  586.         if(marginType == "Top")then
  587.             TFGen.Editor.Cons.mTopBtn     :text(tostring(currentGlyphMargin[marginType]))
  588.         elseif(marginType == "Left")then
  589.             TFGen.Editor.Cons.mLeftBtn    :text(tostring(currentGlyphMargin[marginType]))
  590.         elseif(marginType == "Right")then
  591.             TFGen.Editor.Cons.mRightBtn   :text(tostring(currentGlyphMargin[marginType]))
  592.         end
  593.     else --Value box
  594.         local input = tpt.input("Set Margin "..marginType, "Set the Margin "..marginType.." value ("..-maxVal.."~"..maxVal..")", tostring(currentGlyphMargin[marginType]))
  595.         if(string.len(input)>0)then
  596.             local val = tonumber(input)
  597.             if(val ~= nil and math.abs(val) <= maxVal)then
  598.                 currentGlyphMargin[marginType] = val
  599.                 sender:text(tostring(currentGlyphMargin[marginType]))
  600.             end
  601.         end
  602.     end
  603. end
  604.  
  605. -- Handlers
  606. function TFGen.Editor._KeypressHandler(key, keyNum, modifier, event)
  607.     if(TFGen.Editor.Visable and keyNum ~= 96 and keyNum ~= 122 and keyNum ~= 304 and keyNum ~= 306 and keyNum ~= 308) then -- [~], [z] and modifiers is usable
  608.         return false
  609.     end
  610. end
  611. function TFGen.Editor._ClickHandler(x, y, button, event, scroll) -- button: 0 scroll, 1 left, 2 mid, 4 right; scroll: -1 down, 1 up
  612.     if( button == 0 and scroll == 1) then  -- scroll up
  613.         TFGen.Editor.Commands.Prev()
  614.         return false
  615.     end
  616.     if( button == 0 and scroll == -1) then -- scroll down
  617.         TFGen.Editor.Commands.Next()
  618.         return false
  619.     end
  620. end
  621.  
  622. -- Helper methods
  623. function TFGen.Editor.Show(vis)
  624.     if(vis == nil) then return TFGen.Editor.Visable end
  625.     TFGen.Editor.Visable = vis
  626.     for i, control in pairs(TFGen.Editor.Cons) do
  627.         control:visible(vis)
  628.     end
  629. end
  630. function TFGen.Editor.Reset()
  631.     pcall(tpt.unregister_keypress,   TFGen.Editor._KeypressHandler)
  632.     pcall(tpt.unregister_mouseclick, TFGen.Editor._ClickHandler)
  633.     TFGen.Editor.Show(false)
  634.     TFGen.Editor.Cons = {}
  635.     TFGen.CurrentGlyphIndex = -1
  636. end
  637. function TFGen.Editor.GetClosePos(glyph)            -- Get the proper position close to the glyph
  638.     local properPos = {X=0, Y=0}
  639.     local glyphPos  = {
  640.         X  = glyph.Pos.X ,
  641.         Y  = glyph.Pos.Y ,
  642.         X2 = glyph.Pos.X + glyph.Pos.W,
  643.         Y2 = glyph.Pos.Y + glyph.Pos.H
  644.     }
  645.     if(glyphPos.X > TFGen.MAIN_WIDTH/2)then -- On the right side..
  646.         properPos.X = TFGen.MAIN_WIDTH/2 - 154
  647.     elseif(glyphPos.X2 < TFGen.MAIN_WIDTH/2)then -- On the left side..
  648.         properPos.X = TFGen.MAIN_WIDTH/2 + 10
  649.     else -- Center annoying ones, let's see..
  650.         if(math.abs(glyphPos.X - TFGen.MAIN_WIDTH/2) > math.abs(glyphPos.X2 - TFGen.MAIN_WIDTH/2))then --..more to the left..
  651.             properPos.X = glyphPos.X2 + 10
  652.         else --..more to the right
  653.             properPos.X = glyphPos.X - 154
  654.         end
  655.     end
  656.     -- ..and we can not exceed the main bound.
  657.     if( properPos.X < 0                )then properPos.X = 0                end
  658.     if( properPos.X > TFGen.MAIN_WIDTH )then properPos.X = TFGen.MAIN_WIDTH end
  659.     properPos.Y = TFGen.MAIN_HEIGHT/2 - 77 -- lucy number
  660.     return properPos
  661. end
  662. function TFGen.Editor.MoveTo(pos)                   -- Move to (pos.X, pos.Y)
  663.     for i, control in pairs(TFGen.Editor.Cons) do
  664.         local currentX, currentY = control:position()
  665.         local newPos = {
  666.             X = ( pos.X - TFGen.Editor.Pos.X ) + currentX,
  667.             Y = ( pos.Y - TFGen.Editor.Pos.Y ) + currentY
  668.         }
  669.         control:position(newPos.X, newPos.Y)
  670.     end
  671.     TFGen.Editor.Pos = pos
  672.     TFGen.Editor.UpdateUI()
  673. end
  674. function TFGen.Editor.ChangeIndex(direction, warp)  -- Positive number to +1, negative number to -1. if warp == true, change with loop, default true
  675.     if( warp == nil ) then warp = true end
  676.     if( direction > 0 )then
  677.         if( TFGen.CurrentGlyphIndex < #TFGen.Glyph ) then
  678.             TFGen.CurrentGlyphIndex = TFGen.CurrentGlyphIndex + 1
  679.         elseif( warp ) then
  680.             TFGen.CurrentGlyphIndex = 1 --warp
  681.         end
  682.         TFGen.Editor.UpdateUI()
  683.     end
  684.     if( direction < 0 )then
  685.         if( TFGen.CurrentGlyphIndex > 1 ) then
  686.             TFGen.CurrentGlyphIndex = TFGen.CurrentGlyphIndex - 1
  687.         elseif( warp ) then
  688.             TFGen.CurrentGlyphIndex = #TFGen.Glyph --warp
  689.         end
  690.         TFGen.Editor.UpdateUI()
  691.     end
  692. end
  693. function TFGen.Editor.UpdateUI()                    -- Fresh UI
  694.     if( TFGen.CurrentGlyphIndex > 0 and TFGen.CurrentGlyphIndex <= #TFGen.Glyph ) then
  695.         local currentGlyph = TFGen.Glyph[TFGen.CurrentGlyphIndex]
  696.         if( string.len(currentGlyph.Char) > 0 ) then
  697.             TFGen.Editor.Cons.charBtn   :text( "Char: [ "..currentGlyph.Char.." ]" )
  698.         else
  699.             TFGen.Editor.Cons.charBtn   :text( "Char: []" )
  700.         end
  701.         TFGen.Editor.Cons.mTopBtn   :text( tostring(currentGlyph.Margin.Top  ) )
  702.         TFGen.Editor.Cons.mLeftBtn  :text( tostring(currentGlyph.Margin.Left ) )
  703.         TFGen.Editor.Cons.mRightBtn :text( tostring(currentGlyph.Margin.Right) )
  704.     end
  705. end
  706. function TFGen.Editor.SaveFontToFile(glyph, cachedStr)
  707.     local fontStr = ""
  708.     if( cachedStr ~= nil and string.len(cachedStr) > 0 ) then
  709.         fontStr = cachedStr
  710.     else
  711.         fontStr = "\n--- Font Generated by TFGen ---\n"
  712.         fontStr = fontStr.."\nif(Texter._Fontmatrix == nil) then Texter._Fontmatrix = {} end"
  713.         fontStr = fontStr.."\nTexter._Fontmatrix[\""..glyph.Name.."\"] = {\n\tHeight = "..glyph.Height
  714.         local glyphStr = ""
  715.         for i, glyph in ipairs(glyph) do
  716.             glyphStr = ""
  717.             local char   = "nil"
  718.             local mtx    = {}
  719.             local mtxStr = ""
  720.             if(string.len(glyph.Char) > 0) then
  721.                 char = glyph.Char
  722.             end
  723.             -- Generate mtx str
  724.             for j = 1, #glyph.Mtx do
  725.                 table.insert( mtx, "{"..table.concat(glyph.Mtx[j], ",").."}" )
  726.             end
  727.             mtxStr = "\n\t\t\t"..table.concat(mtx, ",\n\t\t\t")
  728.            
  729.             glyphStr = glyphStr..",\n\t[\""..char.."\"] = {\n\t\tMtx = {"..mtxStr.."\n\t\t}"
  730.             if(glyph.Margin ~= nil and glyph.Margin.Top ~= 0 and glyph.Margin.Left ~= 0 and glyph.Margin.Right ~= 0 )then
  731.                 glyphStr = glyphStr..",\n\t\tMargin = {"
  732.                 glyphStr = glyphStr.."\n\t\t\tTop   = "..glyph.Margin.Top  ..","
  733.                 glyphStr = glyphStr.."\n\t\t\tLeft  = "..glyph.Margin.Left ..","
  734.                 glyphStr = glyphStr.."\n\t\t\tRight = "..glyph.Margin.Right
  735.                 glyphStr = glyphStr.."\n\t\t}"
  736.             end
  737.             glyphStr = glyphStr.."\n\t}"
  738.             fontStr = fontStr..glyphStr
  739.         end
  740.         fontStr = fontStr.."\n}"
  741.     end
  742.     local fontFileName = glyph.Name..".texterfont"
  743.     local file = io.open(fontFileName, "w")
  744.     if file then
  745.         file:write(fontStr)
  746.         file:close()
  747.         local shouldMove = ""
  748.         if( Texter ~= nil and Texter.FONT_FOLDERS_TO_LOAD ~= nil ) then
  749.             shouldMove = tpt.input("File saved", "I can move the font to where it should be, let me try?\nType Yes to continue, anything else to cancel.", "Yes")
  750.         else
  751.             tpt.message_box("File saved", "Font file \""..fontFileName.."\"\nsaved to game dir, please move it to\nthe font folder.")
  752.         end
  753.         if( shouldMove == "Yes" ) then
  754.             TFGen.Editor.MoveFontToFontDir(".", Texter.FONT_FOLDERS_TO_LOAD, fontFileName)
  755.         end
  756.         Texter.Init(false)
  757.     else
  758.         local shouldTryAgain = tpt.input("Unknown Error", "There is an error saving the file, should I try again?\nType Yes to continue, anything else to cancel", "Yes")
  759.         if( shouldTryAgain == "Yes" ) then
  760.             TFGen.Editor.SaveFontToFile(glyph, fontStr) -- Try again
  761.         end
  762.     end
  763. end
  764. function TFGen.Editor.MoveFontToFontDir(rootPath, foldersToLoad, fontFileName)
  765.     local fontFolder = TFGen.Editor.FindDeepestFontFolder(rootPath, foldersToLoad, Texter.FONT_SEARCH_DEPTH)
  766.     local success = false
  767.     if( fontFolder~= nil and string.len(fontFolder) > 0 or foldersToLoad["."] ~= nil ) then -- If . is available, no need to move
  768.         success = fileSystem.move(fontFileName, fontFolder.."\\"..fontFileName)
  769.     end
  770.     if( not success ) then
  771.         tpt.message_box("Move font faild", "Sorry, font file \""..fontFileName.."\"\nfailed to move :(\nPlease move it to \""..fontFolder.."\".")
  772.     end
  773. end
  774. function TFGen.Editor.FindDeepestFontFolder(rootPath, foldersToLoad, depth) -- But not the root folder
  775.     if(  rootPath == nil  ) then
  776.         rootPath = "."
  777.     end
  778.     if(  depth == nil  ) then
  779.         depth = 1
  780.     end
  781.     local fontFolder = nil
  782.     for i, folderName in ipairs(foldersToLoad) do
  783.         if( string.match(rootPath, "\\?"..folderName.."$") ~= nil and rootPath ~= ".") then
  784.             fontFolder = rootPath -- If it's the folder we look for
  785.             break
  786.         end
  787.     end
  788.     -- Let's check the subs for deepest one ( by overwrite fontFolder )
  789.     if(  depth > 0  ) then
  790.         local subs = fs.list(rootPath)
  791.         local subFontFolder = nil
  792.         for i=1, #subs do
  793.             if( Texter._IsFolder(rootPath.."\\"..subs[i]) ) then
  794.                 subFontFolder = TFGen.Editor.FindDeepestFontFolder(rootPath.."\\"..subs[i], foldersToLoad, depth - 1)
  795.             end
  796.             if( subFontFolder ~= nil and string.len(subFontFolder) > 0 ) then  -- Cheers!
  797.                 fontFolder = subFontFolder
  798.                 break
  799.             end
  800.         end
  801.     end
  802.     return fontFolder
  803. end
  804.  
  805. TFGen.Init()
Advertisement
Add Comment
Please, Sign In to add comment