Advertisement
Guest User

TFGen.lua

a guest
Feb 17th, 2013
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- TFGen: Font Generator for Texter
  2. -- Version 0.3.2
  3.  
  4. TFGen = {}
  5. TFGen.MAIN_WIDTH  = 611
  6. TFGen.MAIN_HEIGHT = 383
  7. TFGen.ShowSelectRect = false
  8. TFGen.Drawing = {
  9.     X = 0,
  10.     Y = 0,
  11.     W = 0,
  12.     H = 0,
  13.     Modifier  = 0,
  14.     ArrayMode = false,
  15.     SplitMode = false,
  16.     AreaUndo  = false
  17. }
  18. TFGen.UIItems = {
  19.     -- { --example
  20.         -- Type    = "fill",
  21.         -- Pos     = {X=1, Y=1, W=1, H=1}, --X,Y,X2,Y2 for line
  22.         -- Color   = {R=255, G=255, B=255, A=125},
  23.         -- Life    = 555  --  -1:forever X:stop render after X frames
  24.         -- Fadeout = {From=255, T=30}  --  fadeout(alpha) from, duration, "to" is always 0
  25.     -- }
  26. }
  27. TFGen.GlyphCells = {} -- Structure { {X,Y,W,H} }
  28. TFGen.Glyph      = {} -- Structure: {Height, {Mtx, Pos={X, Y, W, H}, Margin={Left, Right, Top}}}  -- Mtx :{ { {ptype, dcolor..}, {}..},{},.. }
  29. TFGen.Cons       = {} -- Controls
  30. function TFGen.Init(register)
  31.     if( register == nil or register == true ) then
  32.         tpt.register_keypress(TFGen._HotkeyHandler)
  33.     end
  34. end
  35.  
  36. -- Event handlers
  37. function TFGen._HotkeyHandler(key, keyNum, modifier, event)
  38.     if( event==1 ) then -- Modifier record for click event
  39.         if( keyNum == 304 and modifier == 0 ) then TFGen.Drawing.Modifier = 1   end -- shift
  40.         if( keyNum == 306 and modifier == 0 ) then TFGen.Drawing.Modifier = 64  end -- ctrl
  41.         if( keyNum == 308 and modifier == 0 ) then TFGen.Drawing.Modifier = 256 end -- alt
  42.     end
  43.     if( event==2 ) then -- Modifier record for click event
  44.         TFGen.Drawing.Modifier = 0
  45.     end
  46.     if( event==1 and keyNum==116 and modifier==65 ) then -- Ctrl + Shift + t, start
  47.         TFGen.Drawing.X = tpt.mousex
  48.         TFGen.Drawing.Y = tpt.mousey
  49.         TFGen.Drawing.Y = tpt.mousey
  50.         tpt.set_pause(1)
  51.         local notRunning = pcall( tpt.register_step, TFGen._StepHandler )
  52.         pcall( tpt.register_keypress   , TFGen._KeypressHandler)
  53.         pcall( tpt.register_mouseclick , TFGen._ClickHandler   )
  54.         table.insert(
  55.             TFGen.UIItems,
  56.             {
  57.                 Type  = "text",
  58.                 Text  = "Select an area to place glyph rectangle,\nhold Shift to enter Array Mode when selecting.\nLeft click to place, right click to undo.\nEnter to submit, space to cancle.",
  59.                 Pos   = {X=205, Y=190},
  60.                 Color = {R=255, G=255, B=25, A=255},
  61.                 Life  = 150,
  62.                 Fadeout = {From=255, T=60}
  63.             }
  64.         )
  65.         if( notRunning ) then
  66.             table.insert(
  67.                 TFGen.UIItems,
  68.                 {
  69.                     Type  = "text",
  70.                     Text  = "Font Generator for Texter is Running...",
  71.                     Pos   = {X=425, Y=365},
  72.                     Color = {R=255, G=255, B=25, A=155},
  73.                     Life  = -1,
  74.                 }
  75.             )
  76.         end
  77.     end
  78. end
  79. function TFGen._KeypressHandler(key, keyNum, modifier, event)
  80.     if( event==1 and keyNum==13 and modifier==0 and TFGen.Glyph[1] == nil) then   -- Enter submit glyph choice, do not respose when editing
  81.         pcall(tpt.unregister_mouseclick, TFGen._ClickHandler)
  82.         pcall(tpt.unregister_keypress,   TFGen._KeypressHandler)
  83.         TFGen.ShowSelectRect = false
  84.         TFGen.Glyph = TFGen._GlyphGen(TFGen.GlyphCells)
  85.         TFGen.GlyphCells = {}
  86.         TFGen.Editor.Init()
  87.         TFGen.Editor.Show(true)
  88.     end
  89.     if( event==1 and keyNum==32 and modifier==0 ) then   -- Space cancle all
  90.         TFGen.Reset()
  91.     end
  92. end
  93. function TFGen._ClickHandler(x, y, button, event, scroll) -- button: 0 scroll, 1 left, 2 mid, 4 right; scroll: -1 down, 1 up
  94.     if( event == 3 ) then -- Hold
  95.         if( button == 1 or button == 4 ) then -- Resize rectangle
  96.             TFGen.Drawing.W = x - TFGen.Drawing.X
  97.             TFGen.Drawing.H = y - TFGen.Drawing.Y
  98.             if(x > TFGen.MAIN_WIDTH )then TFGen.Drawing.W = TFGen.MAIN_WIDTH  - TFGen.Drawing.X end
  99.             if(y > TFGen.MAIN_HEIGHT)then TFGen.Drawing.H = TFGen.MAIN_HEIGHT - TFGen.Drawing.Y end
  100.         end
  101.         return false
  102.     end
  103.     if( event == 1 ) then -- Mouse down
  104.         if( button == 1 ) then -- Start draw add rectangle
  105.             if(x > TFGen.MAIN_WIDTH )then x = TFGen.MAIN_WIDTH  end
  106.             if(y > TFGen.MAIN_HEIGHT)then y = TFGen.MAIN_HEIGHT end
  107.             TFGen.Drawing.X = x
  108.             TFGen.Drawing.Y = y
  109.             TFGen.ShowSelectRect = true
  110.             if( TFGen.Drawing.Modifier == 1  ) then -- Shift to active glyph array mode
  111.                 TFGen.Drawing.ArrayMode = true
  112.                 TFGen.Drawing.Modifier = 0 -- BUG: no key event fire when out of main window
  113.             end
  114.             if( TFGen.Drawing.Modifier == 64 ) then -- Ctrl to active glyph split mode
  115.                 TFGen.Drawing.SplitMode = true
  116.                 TFGen.Drawing.Modifier = 0 -- BUG: no key event fire when out of main window
  117.             end
  118.         end
  119.         if( button == 4 ) then -- Undo / start area delete
  120.             if( TFGen.Drawing.Modifier == 1 ) then  -- Shift undo all
  121.                 local confirmUndoAll = tpt.input("Undo All", "Are you sure to undo all glyph? Type Yes to confirm.", "Yes")
  122.                 if( confirmUndoAll == "Yes" ) then
  123.                     TFGen.GlyphCells = {}
  124.                 end
  125.                 TFGen.Drawing.Modifier = 0 -- BUG: no key event fire when out of main window
  126.             elseif( TFGen.Drawing.Modifier == 64 ) then  -- Ctrl to start area undo
  127.                 if(x > TFGen.MAIN_WIDTH )then x = TFGen.MAIN_WIDTH  end
  128.                 if(y > TFGen.MAIN_HEIGHT)then y = TFGen.MAIN_HEIGHT end
  129.                 TFGen.Drawing.X = x
  130.                 TFGen.Drawing.Y = y
  131.                 TFGen.ShowSelectRect = true
  132.                 TFGen.Drawing.AreaUndo = true
  133.             else -- Other, simply undo
  134.                 table.remove(TFGen.GlyphCells)
  135.             end
  136.         end
  137.         return false
  138.     end
  139.     if( event == 2 ) then -- Mouse up
  140.         TFGen.ShowSelectRect = false
  141.         if(TFGen.Drawing.W < 0)then
  142.             TFGen.Drawing.W = -1*TFGen.Drawing.W
  143.             TFGen.Drawing.X = TFGen.Drawing.X - TFGen.Drawing.W
  144.         end
  145.         if(TFGen.Drawing.H < 0)then
  146.             TFGen.Drawing.H = -1*TFGen.Drawing.H
  147.             TFGen.Drawing.Y = TFGen.Drawing.Y - TFGen.Drawing.H
  148.         end
  149.         if( button == 1 ) then -- Add rectangle
  150.             if(TFGen.Drawing.W > 0 and TFGen.Drawing.H > 0)then
  151.                 if( not (TFGen.Drawing.ArrayMode or TFGen.Drawing.SplitMode) )then -- Normal mode
  152.                     table.insert(
  153.                         TFGen.GlyphCells,
  154.                         {
  155.                             X = TFGen.Drawing.X,
  156.                             Y = TFGen.Drawing.Y,
  157.                             W = TFGen.Drawing.W,
  158.                             H = TFGen.Drawing.H
  159.                         }
  160.                     )
  161.                 elseif( TFGen.Drawing.SplitMode ) then -- Split mode
  162.                     local glyphGrids = {}
  163.                     local baseRect  = {X=0, Y=0, W=1, H=1}
  164.                     local grid = {Row=1, Col=1}
  165.                     local baseRectStr = tpt.input(
  166.                         "Split Mode",
  167.                         "1. Base rectangle: You can tweak the (x, y, width, height) of your base box:",
  168.                         TFGen.Drawing.X..", "..TFGen.Drawing.Y..", "..TFGen.Drawing.W..", "..TFGen.Drawing.H
  169.                     )
  170.                     local gridStr = tpt.input("Split Mode", "2. Split: The base box will be split to given (rows, columns)", "2, 4")
  171.                     if(baseRectStr ~= nil and gridStr ~= nil) then
  172.                         local count = 0
  173.                         for arg in string.gmatch(baseRectStr, "%d+") do
  174.                             local val = tonumber(arg)
  175.                             -- tpt.log("debug: base"..count.." "..val) --debug
  176.                             if( val ~= nil and val ~= 0) then
  177.                                 if( count == 0 and val <= TFGen.MAIN_WIDTH  )then baseRect.X = val end
  178.                                 if( count == 1 and val <= TFGen.MAIN_HEIGHT )then baseRect.Y = val end
  179.                                 if( count == 2 )then
  180.                                     if(baseRect.X + val <= TFGen.MAIN_WIDTH  )then
  181.                                         baseRect.W = val
  182.                                     else
  183.                                         baseRect.W = TFGen.MAIN_WIDTH  - baseRect.X
  184.                                     end
  185.                                 end
  186.                                 if( count == 3 )then
  187.                                     if( baseRect.Y + val <= TFGen.MAIN_HEIGHT )then
  188.                                         baseRect.H = val
  189.                                     else
  190.                                         baseRect.H = TFGen.MAIN_HEIGHT - baseRect.Y
  191.                                     end
  192.                                 end
  193.                             end
  194.                             count = count + 1
  195.                             if( count >  3 )then break end
  196.                         end
  197.                         count = 0
  198.                         for arg in string.gmatch(gridStr, "%d+") do
  199.                             local val = tonumber(arg)
  200.                             -- tpt.log("debug: array"..count.." "..val) --debug
  201.                             if( val ~= nil and val ~= 0) then
  202.                                 if( count == 0 )then grid.Row = val end
  203.                                 if( count == 1 )then grid.Col = val end
  204.                             end
  205.                             count = count + 1
  206.                             if( count >  1 )then break end
  207.                         end
  208.                         TFGen.Drawing.X = baseRect.X
  209.                         TFGen.Drawing.Y = baseRect.Y
  210.                         TFGen.Drawing.W = baseRect.W / grid.Col
  211.                         TFGen.Drawing.H = baseRect.H / grid.Row
  212.                         local realH = math.floor(TFGen.Drawing.H)
  213.                         for i = 1, grid.Row do
  214.                             TFGen.Drawing.X = baseRect.X
  215.                             for j = 1, grid.Col do
  216.                                 table.insert(
  217.                                     TFGen.GlyphCells,
  218.                                     {
  219.                                         X = math.floor(TFGen.Drawing.X),
  220.                                         Y = math.floor(TFGen.Drawing.Y),
  221.                                         W = TFGen.Drawing.W,
  222.                                         H = realH
  223.                                     }
  224.                                 )
  225.                                 TFGen.Drawing.X = TFGen.Drawing.X + TFGen.Drawing.W
  226.                             end
  227.                             TFGen.Drawing.Y = TFGen.Drawing.Y + TFGen.Drawing.H
  228.                         end
  229.                     end
  230.                 elseif( TFGen.Drawing.ArrayMode ) then -- Array mode
  231.                     -- Edit base box
  232.                     local baseRect  = {X=0, Y=0, W=1, H=1}
  233.                     local arraySize = {Row=1, Col=1}
  234.                     local baseRectStr = tpt.input(
  235.                         "Array Mode",
  236.                         "1. Base rectangle: You can tweak the (x, y, width, height) of your base box:",
  237.                         TFGen.Drawing.X..", "..TFGen.Drawing.Y..", "..TFGen.Drawing.W..", "..TFGen.Drawing.H
  238.                     )
  239.                     local arraySizeStr = tpt.input("Array Mode", "2. Array: The base box will be arrayed with given (rows, columns)", "2, 4")
  240.                     if(baseRectStr ~= nil and arraySizeStr ~= nil) then
  241.                         local count = 0
  242.                         for arg in string.gmatch(baseRectStr, "%d+") do
  243.                             local val = tonumber(arg)
  244.                             -- tpt.log("debug: base"..count.." "..val) --debug
  245.                             if( val ~= nil and val ~= 0) then
  246.                                 if( count == 0 and val <= TFGen.MAIN_WIDTH  )then baseRect.X = val end
  247.                                 if( count == 1 and val <= TFGen.MAIN_HEIGHT )then baseRect.Y = val end
  248.                                 if( count == 2 )then
  249.                                     if(baseRect.X + val <= TFGen.MAIN_WIDTH  )then
  250.                                         baseRect.W = val
  251.                                     else
  252.                                         baseRect.W = TFGen.MAIN_WIDTH  - baseRect.X
  253.                                     end
  254.                                 end
  255.                                 if( count == 3 )then
  256.                                     if( baseRect.Y + val <= TFGen.MAIN_HEIGHT )then
  257.                                         baseRect.H = val
  258.                                     else
  259.                                         baseRect.H = TFGen.MAIN_HEIGHT - baseRect.Y
  260.                                     end
  261.                                 end
  262.                             end
  263.                             count = count + 1
  264.                             if( count >  3 )then break end
  265.                         end
  266.                         count = 0
  267.                         for arg in string.gmatch(arraySizeStr, "%d+") do
  268.                             local val = tonumber(arg)
  269.                             -- tpt.log("debug: array"..count.." "..val) --debug
  270.                             if( val ~= nil and val ~= 0) then
  271.                                 if( count == 0 )then arraySize.Row = val end
  272.                                 if( count == 1 )then arraySize.Col = val end
  273.                             end
  274.                             count = count + 1
  275.                             if( count >  1 )then break end
  276.                         end
  277.                         TFGen.Drawing.X = baseRect.X
  278.                         TFGen.Drawing.Y = baseRect.Y
  279.                         TFGen.Drawing.W = baseRect.W
  280.                         TFGen.Drawing.H = baseRect.H
  281.                         for i = 1, arraySize.Row do
  282.                             TFGen.Drawing.X = baseRect.X
  283.                             for j = 1, arraySize.Col do
  284.                                 table.insert(
  285.                                     TFGen.GlyphCells,
  286.                                     {
  287.                                         X = TFGen.Drawing.X,
  288.                                         Y = TFGen.Drawing.Y,
  289.                                         W = TFGen.Drawing.W,
  290.                                         H = TFGen.Drawing.H
  291.                                     }
  292.                                 )
  293.                                 if( TFGen.Drawing.X + 2*TFGen.Drawing.W <= TFGen.MAIN_WIDTH ) then
  294.                                     TFGen.Drawing.X = TFGen.Drawing.X + TFGen.Drawing.W
  295.                                 else
  296.                                     break
  297.                                 end
  298.                             end
  299.                             if( TFGen.Drawing.Y + 2*TFGen.Drawing.H <= TFGen.MAIN_HEIGHT ) then
  300.                                 TFGen.Drawing.Y = TFGen.Drawing.Y + TFGen.Drawing.H
  301.                             else
  302.                                 break
  303.                             end
  304.                         end
  305.                     end
  306.                 end
  307.             end
  308.             TFGen.Drawing.ArrayMode = false
  309.             TFGen.Drawing.SplitMode = false
  310.         end
  311.         if( button == 4 ) then -- Perform area delete
  312.             if(TFGen.Drawing.W > 0 and TFGen.Drawing.H > 0 and TFGen.Drawing.AreaUndo == true)then
  313.                 local glyphCell = {}
  314.                 local index = 1 -- Lua fool
  315.                 for i = 1, #TFGen.GlyphCells do -- Delete all glyph inside selection
  316.                     glyphCell = TFGen.GlyphCells[index]
  317.                     if( glyphCell ~= nil
  318.                         and glyphCell.X > TFGen.Drawing.X
  319.                         and glyphCell.Y > TFGen.Drawing.Y
  320.                         and glyphCell.X + glyphCell.W < TFGen.Drawing.X + TFGen.Drawing.W
  321.                         and glyphCell.Y + glyphCell.H < TFGen.Drawing.Y + TFGen.Drawing.H
  322.                     ) then
  323.                         table.remove(TFGen.GlyphCells, index)
  324.                     else
  325.                         index = index + 1
  326.                     end
  327.                 end
  328.             end
  329.             TFGen.Drawing.AreaUndo = false
  330.         end
  331.         return false
  332.     end
  333. end
  334. function TFGen._StepHandler()
  335.     TFGen._DrawSelectRect(TFGen.Drawing.X, TFGen.Drawing.Y, TFGen.Drawing.W, TFGen.Drawing.H)
  336.     TFGen._DrawGUI()
  337. end
  338. function TFGen._DrawGUI()
  339.     for i, glyph in ipairs(TFGen.GlyphCells) do
  340.         tpt.drawrect(glyph.X, glyph.Y, glyph.W, glyph.H, 255, 255, 255, 125)
  341.     end
  342.     for i, glyph in ipairs(TFGen.Glyph) do
  343.         if(type(glyph) == "table") then
  344.             local m = {}  -- Short for margin
  345.             local color = {}
  346.             if( glyph.Margin == nil ) then
  347.                 m.top   = 0
  348.                 m.left  = 0
  349.                 m.right = 0
  350.             else
  351.                 if( glyph.Margin.Top   == nil ) then m.top   = 0 else m.top   =  glyph.Margin.Top   end
  352.                 if( glyph.Margin.Left  == nil ) then m.left  = 0 else m.left  =  glyph.Margin.Left  end
  353.                 if( glyph.Margin.Right == nil ) then m.right = 0 else m.right =  glyph.Margin.Right end
  354.             end
  355.             if( i == TFGen.CurrentGlyphIndex )then
  356.                 color  = {R=55 , G=255, B=55 , A=120} -- Glyph rectangle color
  357.                 tcolor = {R=55 , G=255, B=55 , A=200} -- Texte color
  358.                 bcolor = {R=255, G=0  , B=0  , A=120} -- Baseline color
  359.                 -- Dark background
  360.                 local mcolor = {R=0, G=0, B=0, A=200} -- Mask(background) color
  361.                 local maskWidth = 14
  362.                 pcall(  -- Top
  363.                     tpt.fillrect,
  364.                     glyph.Pos.X - m.left - maskWidth,
  365.                     glyph.Pos.Y - m.top  - maskWidth,
  366.                     glyph.Pos.W + m.left + m.right + 2*maskWidth,
  367.                     maskWidth,
  368.                     mcolor.R, mcolor.G, mcolor.B, mcolor.A
  369.                 )
  370.                 pcall(  -- Bottom
  371.                     tpt.fillrect,
  372.                     glyph.Pos.X - m.left - maskWidth,
  373.                     glyph.Pos.Y - m.top  + TFGen.Glyph.Height,
  374.                     glyph.Pos.W + m.left + m.right + 2*maskWidth,
  375.                     maskWidth,
  376.                     mcolor.R, mcolor.G, mcolor.B, mcolor.A
  377.                 )
  378.                 pcall(  -- Left
  379.                     tpt.fillrect,
  380.                     glyph.Pos.X - m.left - maskWidth,
  381.                     glyph.Pos.Y - m.top - 1,
  382.                     maskWidth,
  383.                     TFGen.Glyph.Height + 2, -- No matter what glyph.Pos.H is
  384.                     mcolor.R, mcolor.G, mcolor.B, mcolor.A
  385.                 )
  386.                 pcall(  -- Right
  387.                     tpt.fillrect,
  388.                     glyph.Pos.X + glyph.Pos.W + m.right,
  389.                     glyph.Pos.Y - m.top - 1,
  390.                     maskWidth,
  391.                     TFGen.Glyph.Height + 2, -- No matter what glyph.Pos.H is
  392.                     mcolor.R, mcolor.G, mcolor.B, mcolor.A
  393.                 )
  394.             else
  395.                 color  = {R=55 , G=255, B=55 , A=50 } -- Glyph rectangle color
  396.                 tcolor = {R=55 , G=255, B=55 , A=60 } -- Texte color
  397.                 bcolor = {R=255, G=0  , B=0  , A=50 } -- Baseline color
  398.             end
  399.             pcall(  -- Room rectangle
  400.                 tpt.drawrect,
  401.                 glyph.Pos.X - m.left,
  402.                 glyph.Pos.Y - m.top ,
  403.                 glyph.Pos.W + m.left + m.right,
  404.                 TFGen.Glyph.Height, -- No matter what glyph.Pos.H is
  405.                 color.R, color.G, color.B, color.A
  406.             )
  407.             pcall(  -- baseline
  408.                 tpt.drawline,
  409.                 glyph.Pos.X - m.left - glyph.Pos.W/4,
  410.                 glyph.Pos.Y - m.top  + TFGen.Glyph.Height, -- No matter what glyph.Pos.H is
  411.                 glyph.Pos.X + m.left + m.right + glyph.Pos.W*5/4,
  412.                 glyph.Pos.Y - m.top  + TFGen.Glyph.Height, -- No matter what glyph.Pos.H is
  413.                 bcolor.R, bcolor.G, bcolor.B, bcolor.A
  414.             )
  415.             local char = glyph.Char
  416.             if( char ~= nil) then
  417.                 if( char == " " ) then char = "space" end -- Special
  418.                 pcall(  -- Assigned character
  419.                     tpt.drawtext,
  420.                     glyph.Pos.X - m.left,
  421.                     glyph.Pos.Y - m.top - 10, -- Default font height + 3?
  422.                     i..":"..char,
  423.                     tcolor.R, tcolor.G, tcolor.B, tcolor.A
  424.                 )
  425.             end
  426.         end
  427.     end
  428.     for i, item  in ipairs(TFGen.UIItems) do
  429.         --Few types, so if-else-if won't be performance critical
  430.         if item.Pos      == nil then item.Pos     = {X=1, Y=1, X2=1, Y2=1, W=1, H=1} end
  431.         if item.Color    == nil then item.Color   = {R=255, G=255, B=255, A=125} end
  432.         if item.Fadeout  == nil then item.Fadeout = {From = 255, T=0}  end
  433.         if item.Life     == nil then item.Life    = 60 end
  434.         if item.Text     == nil then item.Text    = "" end
  435.        
  436.         if(item.Life > 0 or item.Life == -1) then
  437.             if(item.Life > 0)then item.Life = item.Life - 1 end
  438.             --fadeout, no fadeout for forever ones
  439.             if(item.Life <= item.Fadeout.T and item.Life ~= -1)then
  440.                 item.Color.A = item.Fadeout.From * item.Life/item.Fadeout.T
  441.             end
  442.             if(item.Type == "text") then
  443.                 tpt.drawtext(item.Pos.X, item.Pos.Y, item.Text, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  444.             elseif (item.Type == "pixel") then
  445.                 tpt.drawpixel(item.Pos.X, item.Pos.Y, item.Color.R, item.Color.G, item.Color.B, item.Color.A)
  446.             elseif (item.Type == "line") then
  447.                 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)
  448.             elseif (item.Type == "rect") then
  449.                 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)
  450.             elseif (item.Type == "fill" ) then
  451.                 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)
  452.             end
  453.         else -- You were dead
  454.             table.remove(TFGen.UIItems, i)
  455.             i = i-1 --Lua will shifting down other elements to close the space, so we might jump one item off without this
  456.         end
  457.     end
  458. end
  459. function TFGen._DrawSelectRect(posX, posY, width, height)
  460.     if(width < 0)then
  461.         width = -1*width
  462.         posX = posX - width
  463.     end
  464.     if(height < 0)then
  465.         height = -1*height
  466.         posY = posY - height
  467.     end
  468.     if(TFGen.ShowSelectRect)then
  469.         tpt.drawrect(posX, posY, width, height, 255, 255, 255, 125)
  470.     end
  471. end
  472.  
  473. -- Generate glyph
  474. function TFGen._GlyphGen(glyphCells)
  475.     local glyphList  = {}
  476.     glyphList.Name   = "font1"
  477.     glyphList.Height = -1
  478.     glyphList.Mode   = 3 -- 0: only shape, +1: ptype, +2: dcolor +4: TODO? life, temp, etc.
  479.     for index, glyph in ipairs(glyphCells) do
  480.         -- Minimum Bound Box detection, using the stupid methods, generally O(n), worst O(n^2)
  481.         local mbb = {}
  482.         local foundTopBound    = false -- First top non-empty flag
  483.         local foundBottomBound = false -- First bottom non-empty flag
  484.         for i = 0, glyph.H - 1 do
  485.             for j = 0, glyph.W - 1 do
  486.                 if(tpt.get_property("type", glyph.X + j, glyph.Y + i) ~= 0 and foundTopBound == false)then
  487.                     mbb.top    = glyph.Y + i           -- The first top non-empty row
  488.                     foundTopBound = true
  489.                 end
  490.                 if(tpt.get_property("type", glyph.X + j, glyph.Y + glyph.H - i) ~= 0 and foundBottomBound == false)then
  491.                     mbb.bottom = glyph.Y + glyph.H - i -- The first bottom non-empty row
  492.                     foundBottomBound = true
  493.                 end
  494.                 if( foundTopBound and foundBottomBound ) then break end
  495.             end
  496.             if( foundTopBound and foundBottomBound ) then break end
  497.         end
  498.         local foundLeftBound  = false -- First left non-empty flag
  499.         local foundRightBound = false -- First right non-empty flag
  500.         for i = 0, glyph.W - 1 do
  501.             for j = 0, glyph.H - 1 do
  502.                 if(tpt.get_property("type", glyph.X + i, glyph.Y + j) ~= 0 and foundLeftBound == false)then
  503.                     mbb.left  = glyph.X + i           -- The first left non-empty column
  504.                     foundLeftBound = true
  505.                 end
  506.                 if(tpt.get_property("type", glyph.X + glyph.W - i, glyph.Y + j) ~= 0 and foundRightBound == false)then
  507.                     mbb.right = glyph.X + glyph.W - i -- The first right non-empty column
  508.                     foundRightBound = true
  509.                 end
  510.                 if( foundLeftBound and foundRightBound ) then break end
  511.             end
  512.             if( foundLeftBound and foundRightBound ) then break end
  513.         end
  514.        
  515.         if(mbb.left ~= nil and mbb.right ~= nil and mbb.top ~= nil and mbb.bottom ~= nil) then
  516.             -- tpt.log("top:"..mbb.top..",left:"..mbb.left..",bottom:"..mbb.bottom..",right:"..mbb.right) -- debug
  517.             local glyphArea = {X=mbb.left, Y=mbb.top, W=(mbb.right - mbb.left)+1, H=(mbb.bottom - mbb.top)+1}
  518.             local mtx       = TFGen._DigitizeArea(glyphArea)
  519.             if( (mbb.bottom - mbb.top) >= glyphList.Height) then
  520.                 glyphList.Height = mbb.bottom - mbb.top + 1
  521.             end
  522.             table.insert(
  523.                 glyphList,
  524.                 {
  525.                     Char   = "",
  526.                     Mtx    = mtx,
  527.                     Pos    = glyphArea,
  528.                     Margin = {Top= 0, Left=0, Right=0}
  529.                 }
  530.             )
  531.         end
  532.     end
  533.     for index, glyph in ipairs(glyphList) do -- Try to put all glyph on their baseline
  534.         glyph.Margin.Top = glyphList.Height - glyph.Pos.H
  535.     end
  536.     return glyphList
  537. end
  538. -- Digitize selected area
  539. function TFGen._DigitizeArea(area)
  540.     local mtx = {}
  541.     local x1 = area.X
  542.     local x2 = area.X + area.W - 1
  543.     local y1 = area.Y
  544.     local y2 = area.Y + area.H - 1
  545.    
  546.     if(area ~= nil and area.X ~= nil and area.Y ~= nil and area.W ~= nil and area.H ~= nil)then
  547.         for y = y1, y2 do
  548.             local row = {}
  549.             for x = x1, x2 do
  550.                 local particle = {ptype=0, dcolor=0}
  551.                 local isGetPtypeSucceed, ptype  = pcall(tpt.get_property, "type", x, y)
  552.                 if( isGetPtypeSucceed )then
  553.                     particle.ptype = ptype
  554.                     local isGetDcolorSucceed, dcolor = pcall(tpt.get_property, "dcolour", x, y)
  555.                     if( isGetDcolorSucceed )then
  556.                         particle.dcolor = dcolor
  557.                     end
  558.                 end
  559.                 table.insert(row, particle)
  560.             end
  561.             table.insert(mtx, row)
  562.         end
  563.     end
  564.     return mtx
  565. end
  566. -- Reset
  567. function TFGen.Reset()
  568.     pcall(tpt.unregister_step,       TFGen._StepHandler)
  569.     pcall(tpt.unregister_keypress,   TFGen._KeypressHandler)
  570.     pcall(tpt.unregister_mouseclick, TFGen._ClickHandler)
  571.     TFGen.ShowSelectRect = false
  572.     TFGen.GlyphCells = {}
  573.     TFGen.Glyph = {}
  574.     TFGen.UIItems = {}
  575. end
  576.  
  577.  
  578. -- The glyph editor after font generation
  579. TFGen.Editor = {}
  580. TFGen.Editor.Cons = {} -- Controls bag
  581. TFGen.Editor.Pos  = {X=100, Y=100}
  582. TFGen.Editor.Visable = true
  583. TFGen.CurrentGlyphIndex = -1
  584. function TFGen.Editor.Init()
  585.     -- If no glyph generated, quit
  586.     if(TFGen.Glyph.Height == nil or TFGen.Glyph[1] == nil)then
  587.         TFGen.Reset()
  588.         TFGen.Editor.Reset()
  589.         return false
  590.     end
  591.     tpt.register_keypress(TFGen.Editor._KeypressHandler)
  592.     tpt.register_mouseclick(TFGen.Editor._ClickHandler)
  593.     TFGen.CurrentGlyphIndex = 1
  594.     local controlHeight = 14
  595.     -- Position to show
  596.     local properPos = TFGen.Editor.GetClosePos(TFGen.Glyph[TFGen.CurrentGlyphIndex])
  597.     TFGen.Editor.Pos.X = properPos.X
  598.     TFGen.Editor.Pos.Y = properPos.Y
  599.     local editorX = properPos.X
  600.     local editorY = properPos.Y
  601.     local editorW = 144
  602.    
  603.     local lines = 0    -- 1st line : 0
  604.     local prevBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Prev"                       )
  605.     local nextBtn      = Button:new( editorX + editorW/2  , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Next"                       )
  606.     lines = lines + 2  -- 2nd line : 2
  607.     local nameBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Name: "..TFGen.Glyph.Name   )
  608.     lines = lines + 1  -- 3rd line : 3
  609.     local charBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Char: []"                   )
  610.     lines = lines + 1  -- 4th line : 4
  611.     local modeBtn      = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Mode: "..TFGen.Glyph.Mode   )
  612.     lines = lines + 1  -- 5th line : 4
  613.     local autoCharBtn  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Auto assign"                )
  614.     lines = lines + 1  -- 6th line : 5
  615.     local heightLabel  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Font Height"                )
  616.     local heightDecBtn = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  617.     local heightBtn    = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  tostring(TFGen.Glyph.Height) )
  618.     local heightIncBtn = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  619.     lines = lines + 1  -- 7th line : 6
  620.     local mTopLabel    = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Top"                 )
  621.     local mTopDecBtn   = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  622.     local mTopBtn      = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  623.     local mTopIncBtn   = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  624.     lines = lines + 1  -- 8th line : 7
  625.     local mLeftLabel   = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Left"                )
  626.     local mLeftDecBtn  = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  627.     local mLeftBtn     = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  628.     local mLeftIncBtn  = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  629.     lines = lines + 1  -- 9th line : 8
  630.     local mRightLabel  = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight     + 1,  "Margin Right"               )
  631.     local mRightDecBtn = Button:new( editorX + editorW*3/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "-"                          )
  632.     local mRightBtn    = Button:new( editorX + editorW*4/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "0"                          )
  633.     local mRightIncBtn = Button:new( editorX + editorW*5/6, editorY + controlHeight * lines ,   editorW/6 + 1,  controlHeight     + 1,  "+"                          )
  634.     lines = lines + 1  -- 10th line : 9
  635.     local deleteBtn    = Button:new( editorX              , editorY + controlHeight * lines ,   editorW   + 1,  controlHeight     + 1,  "Delete this glyph (No undo)")
  636.     lines = lines + 1  -- 11th line : 10
  637.     local cancelAllBtn = Button:new( editorX              , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Cancel All"                 )
  638.     local submitAllBtn = Button:new( editorX + editorW/2  , editorY + controlHeight * lines ,   editorW/2 + 1,  controlHeight * 2 + 1,  "Submit All"                 )
  639.    
  640.     prevBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Prev"      ,    sender) end )
  641.     nextBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Next"      ,    sender) end )
  642.     nameBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Name"      ,    sender) end )
  643.     charBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Char"      ,    sender) end )
  644.     modeBtn     :action ( function(sender) TFGen.Editor.CommandHandler("Mode"      ,    sender) end )
  645.     autoCharBtn :action ( function(sender) TFGen.Editor.CommandHandler("AutoAssign",    sender) end )
  646.     heightDecBtn:action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  647.     heightBtn   :action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  648.     heightIncBtn:action ( function(sender) TFGen.Editor.CommandHandler("HeightMod" ,    sender) end )
  649.     mTopDecBtn  :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  650.     mTopBtn     :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  651.     mTopIncBtn  :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  652.     mLeftDecBtn :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  653.     mLeftBtn    :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  654.     mLeftIncBtn :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  655.     mRightDecBtn:action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  656.     mRightBtn   :action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  657.     mRightIncBtn:action ( function(sender) TFGen.Editor.CommandHandler("MarginMod" ,    sender) end )
  658.     deleteBtn   :action ( function(sender) TFGen.Editor.CommandHandler("Delete"    ,    sender) end )
  659.     cancelAllBtn:action ( function(sender) TFGen.Editor.CommandHandler("CancelAll" ,    sender) end )
  660.     submitAllBtn:action ( function(sender) TFGen.Editor.CommandHandler("SubmitAll" ,    sender) end )
  661.    
  662.     TFGen.Editor.Cons.prevBtn      = prevBtn
  663.     TFGen.Editor.Cons.nextBtn      = nextBtn
  664.     TFGen.Editor.Cons.nameBtn      = nameBtn
  665.     TFGen.Editor.Cons.charBtn      = charBtn
  666.     TFGen.Editor.Cons.modeBtn      = modeBtn
  667.     TFGen.Editor.Cons.autoCharBtn  = autoCharBtn
  668.     TFGen.Editor.Cons.heightLabel  = heightLabel
  669.     TFGen.Editor.Cons.heightDecBtn = heightDecBtn
  670.     TFGen.Editor.Cons.heightBtn    = heightBtn
  671.     TFGen.Editor.Cons.heightIncBtn = heightIncBtn
  672.     TFGen.Editor.Cons.mTopLabel    = mTopLabel
  673.     TFGen.Editor.Cons.mTopDecBtn   = mTopDecBtn
  674.     TFGen.Editor.Cons.mTopBtn      = mTopBtn
  675.     TFGen.Editor.Cons.mTopIncBtn   = mTopIncBtn
  676.     TFGen.Editor.Cons.mLeftLabel   = mLeftLabel
  677.     TFGen.Editor.Cons.mLeftDecBtn  = mLeftDecBtn
  678.     TFGen.Editor.Cons.mLeftBtn     = mLeftBtn
  679.     TFGen.Editor.Cons.mLeftIncBtn  = mLeftIncBtn
  680.     TFGen.Editor.Cons.mRightLabel  = mRightLabel
  681.     TFGen.Editor.Cons.mRightDecBtn = mRightDecBtn
  682.     TFGen.Editor.Cons.mRightBtn    = mRightBtn
  683.     TFGen.Editor.Cons.mRightIncBtn = mRightIncBtn
  684.     TFGen.Editor.Cons.cancelAllBtn = cancelAllBtn
  685.     TFGen.Editor.Cons.submitAllBtn = submitAllBtn
  686.     TFGen.Editor.Cons.deleteBtn    = deleteBtn
  687.    
  688.     interface.addComponent(heightLabel )
  689.     interface.addComponent(mTopLabel   )
  690.     interface.addComponent(mLeftLabel  )
  691.     interface.addComponent(mRightLabel )
  692.    
  693.     interface.addComponent(prevBtn     )
  694.     interface.addComponent(nextBtn     )
  695.     interface.addComponent(nameBtn     )
  696.     interface.addComponent(charBtn     )
  697.     interface.addComponent(modeBtn     )
  698.     interface.addComponent(autoCharBtn )
  699.     interface.addComponent(heightDecBtn)
  700.     interface.addComponent(heightBtn   )
  701.     interface.addComponent(heightIncBtn)
  702.     interface.addComponent(mTopDecBtn  )
  703.     interface.addComponent(mTopBtn     )
  704.     interface.addComponent(mTopIncBtn  )
  705.     interface.addComponent(mLeftDecBtn )
  706.     interface.addComponent(mLeftBtn    )
  707.     interface.addComponent(mLeftIncBtn )
  708.     interface.addComponent(mRightDecBtn)
  709.     interface.addComponent(mRightBtn   )
  710.     interface.addComponent(mRightIncBtn)
  711.     interface.addComponent(deleteBtn   )
  712.     interface.addComponent(cancelAllBtn)
  713.     interface.addComponent(submitAllBtn)
  714. end
  715.  
  716. -- Command handler
  717. function TFGen.Editor.CommandHandler(command, sender)
  718.     local success, errorMessage = pcall(TFGen.Editor.Commands[command], sender)
  719.     if(success == false) then
  720.         tpt.log("TFGen: Error in command \""..command.."\": "..errorMessage)
  721.     end
  722. end
  723. -- Commands
  724. TFGen.Editor.Commands = {}
  725. function TFGen.Editor.Commands.CancelAll()
  726.     TFGen.Reset()
  727.     TFGen.Editor.Reset()
  728. end
  729. function TFGen.Editor.Commands.SubmitAll()
  730.     if( TFGen.Glyph ~= nil ) then
  731.         TFGen.Editor.SaveFontToFile(TFGen.Glyph)
  732.     else
  733.         tpt.message_box("Font not saved", "No glyph found, no font saved, human.")
  734.     end
  735.     TFGen.Reset()
  736.     TFGen.Editor.Reset()
  737. end
  738. function TFGen.Editor.Commands.Prev(step)
  739.     TFGen.Editor.ChangeIndex(-step)
  740.     TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  741. end
  742. function TFGen.Editor.Commands.Next(step)
  743.     TFGen.Editor.ChangeIndex(step)
  744.     TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  745. end
  746. function TFGen.Editor.Commands.Name(sender)
  747.     local input = tpt.input("Font name", "Set the name for your font", TFGen.Glyph.Name)
  748.     if(string.len(input)>0)then
  749.         input = string.gsub(input, "[^%l%u%d_]*", "")
  750.         input = string.gsub(input, "^%d+", "")
  751.         TFGen.Glyph.Name = input
  752.         sender:text("Name: "..TFGen.Glyph.Name)
  753.     end
  754. end
  755. function TFGen.Editor.Commands.Char(sender)
  756.     local currentGlyph = TFGen.Glyph[TFGen.CurrentGlyphIndex]
  757.     local input = tpt.input("Assign the character", "Assign the character for this glyph")
  758.     if(string.len(input)>0)then
  759.         currentGlyph.Char = string.sub(input, 1, 1)
  760.         sender:text("Char: [ "..currentGlyph.Char.." ]")
  761.     else
  762.         currentGlyph.Char = ""
  763.         sender:text("Char: []")
  764.     end
  765. end
  766. function TFGen.Editor.Commands.Mode(sender)
  767.     local mode = tpt.input("Font file mode", "Information saved to font:\n0  only save shape.\n+1: and ptype.\n+2: and dcolor.\nAdd your choices up then type in.")
  768.     mode = tonumber(mode)
  769.     if( mode~= nil and mode >= 0 )then
  770.         TFGen.Glyph.Mode = mode
  771.         sender:text("Mode: "..TFGen.Glyph.Mode)
  772.     end
  773. end
  774. -- Auto assign characters from current index with given sequence:
  775. -- 0~9, A~Z, a~z, *space*`-=[]\;',./~!@#$%^&*()_+{}|:"<>? (all symbols then shift-symbols)
  776. function TFGen.Editor.Commands.AutoAssign()
  777.     local input = tpt.input("Auto assign", "Auto assign characters from current glyph in order: 0~9, A~Z, a~z, space`-=[]\\;',./~!@#$%^&*()_+{}|:\"<>? (the keyboard order)\n0  Clear assigned ones.\n+1 0~9 only\n+2 Upper characters only.\n+4 Lower characters only.\n+8 Symbols only.\nAdd your choices up then type in.", "15", "Any input out of 0~15 will be ignored")
  778.     input = tonumber(input)
  779.     if( input ~= nil and input >= 0 ) then
  780.         -- Auto assign in sequence
  781.         local index        = TFGen.CurrentGlyphIndex
  782.         local glyphCount   = #TFGen.Glyph
  783.         -- Clear assigned ones
  784.         if( bit.bor(input, 0) == 0 ) then
  785.             for i = index, glyphCount do
  786.                 if( TFGen.Glyph[index] ~= nil ) then
  787.                     TFGen.Glyph[index].Char = ""
  788.                     index = index + 1
  789.                 end
  790.             end
  791.         else
  792.             -- 0~9
  793.             if( bit.band(input, 1) == 1 ) then
  794.                 for i = 0, 9 do
  795.                     if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  796.                         TFGen.Glyph[index].Char = string.char( 48 + i )
  797.                         index = index + 1
  798.                     else
  799.                         break
  800.                     end
  801.                 end
  802.             end
  803.             -- Upper chars
  804.             if( bit.band(input, 2) == 2 ) then
  805.                 for i = 0, 25 do
  806.                     if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  807.                         TFGen.Glyph[index].Char = string.char( 65 + i )
  808.                         index = index + 1
  809.                     else
  810.                         break
  811.                     end
  812.                 end
  813.             end
  814.             -- Lower chars
  815.             if( bit.band(input, 4) == 4 ) then
  816.                 for i = 0, 25 do
  817.                     if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  818.                         TFGen.Glyph[index].Char = string.char( 97 + i )
  819.                         index = index + 1
  820.                     else
  821.                         break
  822.                     end
  823.                 end
  824.             end
  825.             -- Symbols, ordered in logic sequence to deliver better experience for font creators
  826.             if( bit.band(input, 8) == 8) then
  827.                 local symbolMap = {" ", "`", "-", "=", "[", "]", "\\", ";", "'", ",", ".", "/", "~", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "+", "{", "}", "|", ":", "\"", "<", ">", "?"}
  828.                 for i = 1, 33 do -- All symbols count: 1 + 32
  829.                     if( TFGen.Glyph[index] ~= nil and index <= glyphCount ) then
  830.                         TFGen.Glyph[index].Char = symbolMap[ i ]
  831.                         index = index + 1
  832.                     else
  833.                         break
  834.                     end
  835.                 end
  836.             end
  837.             -- Clear the rest
  838.             -- if( index < glyphCount ) then
  839.                 -- for i = index, glyphCount do
  840.                     -- TFGen.Glyph[index].Char = ""
  841.                     -- index = index + 1
  842.                 -- end
  843.             -- end
  844.         end
  845.         TFGen.Editor.UpdateUI()
  846.     end
  847. end
  848. function TFGen.Editor.Commands.Delete()
  849.     table.remove(TFGen.Glyph, TFGen.CurrentGlyphIndex)
  850.     if(#TFGen.Glyph < 1) then -- No one left
  851.         TFGen.Reset()
  852.         TFGen.Editor.Reset()
  853.     elseif(TFGen.Glyph[TFGen.CurrentGlyphIndex] == nil) then -- We just kill the last one
  854.         TFGen.Editor.ChangeIndex(-1)
  855.         TFGen.Editor.MoveTo( TFGen.Editor.GetClosePos( TFGen.Glyph[TFGen.CurrentGlyphIndex] ) )
  856.     end
  857. end
  858. function TFGen.Editor.Commands.HeightMod(sender)
  859.     local opt = sender:text()
  860.     local optList = { ["+"]=1, ["-"]=-1 }
  861.     if(opt == "+" or opt == "-")then -- Increase/Decrease btn
  862.         TFGen.Glyph.Height = TFGen.Glyph.Height + optList[opt]
  863.         TFGen.Editor.Cons.heightBtn:text(tostring(TFGen.Glyph.Height))
  864.     else --Height box
  865.         local input = tpt.input("Set font height", "Set the font height for all glyph (1~"..TFGen.MAIN_HEIGHT..")", tostring(TFGen.Glyph.Height))
  866.         if(string.len(input)>0)then
  867.             local h = tonumber(input)
  868.             if(h ~= nil and h > 0 and h <= TFGen.MAIN_HEIGHT)then
  869.                 TFGen.Glyph.Height = h
  870.                 sender:text(tostring(TFGen.Glyph.Height))
  871.             end
  872.         end
  873.     end
  874. end
  875. function TFGen.Editor.Commands.MarginMod(sender)
  876.     local opt = sender:text()
  877.     local optList = { ["+"]=1, ["-"]=-1 }
  878.     local currentGlyphMargin = TFGen.Glyph[TFGen.CurrentGlyphIndex].Margin
  879.     local marginType = ""
  880.     local maxVal = 0
  881.     if(     sender == TFGen.Editor.Cons.mTopDecBtn   or sender == TFGen.Editor.Cons.mTopIncBtn   or sender == TFGen.Editor.Cons.mTopBtn  )then
  882.         marginType = "Top"
  883.         maxVal = TFGen.MAIN_HEIGHT - 1
  884.     elseif( sender == TFGen.Editor.Cons.mLeftDecBtn  or sender == TFGen.Editor.Cons.mLeftIncBtn  or sender == TFGen.Editor.Cons.mLeftBtn )then
  885.         marginType = "Left"
  886.         maxVal = TFGen.MAIN_WIDTH - 1
  887.     elseif( sender == TFGen.Editor.Cons.mRightDecBtn or sender == TFGen.Editor.Cons.mRightIncBtn or sender == TFGen.Editor.Cons.mRightBtn)then
  888.         marginType = "Right"
  889.         maxVal = TFGen.MAIN_WIDTH - 1
  890.     end
  891.     if(opt == "+" or opt == "-")then -- Increase/Decrease btn
  892.         if( TFGen.Drawing.Modifier == 0 ) then -- None, single operation
  893.             currentGlyphMargin[marginType] = currentGlyphMargin[marginType] + optList[opt]
  894.         elseif( TFGen.Drawing.Modifier == 1 ) then -- Shift, operate all glyph
  895.             for i = 1, #TFGen.Glyph do
  896.                 TFGen.Glyph[i].Margin[marginType] = TFGen.Glyph[i].Margin[marginType] + optList[opt]
  897.             end
  898.         end
  899.         -- tpt.log("Modifier is: "..TFGen.Drawing.Modifier)-- debug
  900.         if(marginType == "Top")then
  901.             TFGen.Editor.Cons.mTopBtn     :text(tostring(currentGlyphMargin[marginType]))
  902.         elseif(marginType == "Left")then
  903.             TFGen.Editor.Cons.mLeftBtn    :text(tostring(currentGlyphMargin[marginType]))
  904.         elseif(marginType == "Right")then
  905.             TFGen.Editor.Cons.mRightBtn   :text(tostring(currentGlyphMargin[marginType]))
  906.         end
  907.     else --Value box
  908.         local inputTitle = ""
  909.         local inputHead  = ""
  910.         if( TFGen.Drawing.Modifier == 0 ) then -- None, single operation
  911.             inputTitle = "Set Margin "
  912.             inputHead  = "Set the Margin "
  913.         elseif( TFGen.Drawing.Modifier == 1 ) then -- Shift, operate all glyph
  914.             inputTitle = "Set All Glyph's Margin "
  915.             inputHead  = "Set all glyph's Margin "
  916.         end
  917.         local input = tpt.input(inputTitle..marginType, inputHead..marginType.." value ("..-maxVal.."~"..maxVal..")")
  918.         if(string.len(input)>0)then
  919.             local val = tonumber(input)
  920.             if(val ~= nil and math.abs(val) <= maxVal)then
  921.                 if( TFGen.Drawing.Modifier == 0 ) then -- None, single operation
  922.                     currentGlyphMargin[marginType] = val
  923.                 elseif( TFGen.Drawing.Modifier == 1 ) then -- Shift, operate all glyph
  924.                     for i = 1, #TFGen.Glyph do
  925.                         TFGen.Glyph[i].Margin[marginType] = val
  926.                     end
  927.                 end
  928.                 sender:text(tostring(currentGlyphMargin[marginType]))
  929.             end
  930.         end
  931.         TFGen.Drawing.Modifier = 0
  932.     end
  933. end
  934.  
  935. -- Handlers
  936. function TFGen.Editor._KeypressHandler(key, keyNum, modifier, event)
  937.     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
  938.         return false
  939.     end
  940. end
  941. function TFGen.Editor._ClickHandler(x, y, button, event, scroll) -- button: 0 scroll, 1 left, 2 mid, 4 right; scroll: -1 down, 1 up
  942.     local step = 1
  943.     if( TFGen.Drawing.Modifier == 1 ) then -- Shift for 5
  944.         step = 5
  945.     end
  946.     if( button == 0 and scroll == 1) then  -- Scroll up
  947.         TFGen.Editor.Commands.Prev(step)
  948.         return false
  949.     end
  950.     if( button == 0 and scroll == -1) then -- Scroll down
  951.         TFGen.Editor.Commands.Next(step)
  952.         return false
  953.     end
  954. end
  955.  
  956. -- Helper methods
  957. function TFGen.Editor.Show(vis)
  958.     if(vis == nil) then return TFGen.Editor.Visable end
  959.     TFGen.Editor.Visable = vis
  960.     for id, control in pairs(TFGen.Editor.Cons) do
  961.         control:visible(vis)
  962.     end
  963. end
  964. function TFGen.Editor.Reset()
  965.     pcall(tpt.unregister_keypress,   TFGen.Editor._KeypressHandler)
  966.     pcall(tpt.unregister_mouseclick, TFGen.Editor._ClickHandler)
  967.     TFGen.Editor.Show(false)
  968.     TFGen.Editor.Cons = {}
  969.     TFGen.CurrentGlyphIndex = -1
  970. end
  971. function TFGen.Editor.GetClosePos(glyph)            -- Get the proper position close to the glyph
  972.     local properPos = {X=0, Y=0}
  973.     local glyphPos  = {
  974.         X  = glyph.Pos.X ,
  975.         Y  = glyph.Pos.Y ,
  976.         X2 = glyph.Pos.X + glyph.Pos.W,
  977.         Y2 = glyph.Pos.Y + glyph.Pos.H
  978.     }
  979.     if(glyphPos.X > TFGen.MAIN_WIDTH/2)then -- On the right side..
  980.         properPos.X = TFGen.MAIN_WIDTH/2 - 154
  981.     elseif(glyphPos.X2 < TFGen.MAIN_WIDTH/2)then -- On the left side..
  982.         properPos.X = TFGen.MAIN_WIDTH/2 + 10
  983.     else -- Center annoying ones, let's see..
  984.         if(math.abs(glyphPos.X - TFGen.MAIN_WIDTH/2) > math.abs(glyphPos.X2 - TFGen.MAIN_WIDTH/2))then --..more to the left..
  985.             properPos.X = glyphPos.X2 + 10
  986.             -- Editor width: 144
  987.             if( properPos.X + 144 > TFGen.MAIN_WIDTH ) then
  988.                 properPos.X = TFGen.MAIN_WIDTH - 144
  989.             end
  990.         else --..more to the right
  991.             properPos.X = glyphPos.X - 154
  992.         end
  993.     end
  994.     -- ..and we can not exceed the main bound.
  995.     if( properPos.X < 0                )then properPos.X = 0                end
  996.     if( properPos.X > TFGen.MAIN_WIDTH )then properPos.X = TFGen.MAIN_WIDTH end
  997.     properPos.Y = TFGen.MAIN_HEIGHT/2 - 77 -- lucy number
  998.     return properPos
  999. end
  1000. function TFGen.Editor.MoveTo(pos)                   -- Move to (pos.X, pos.Y)
  1001.     for id, control in pairs(TFGen.Editor.Cons) do
  1002.         local currentX, currentY = control:position()
  1003.         local newPos = {
  1004.             X = ( pos.X - TFGen.Editor.Pos.X ) + currentX,
  1005.             Y = ( pos.Y - TFGen.Editor.Pos.Y ) + currentY
  1006.         }
  1007.         control:position(newPos.X, newPos.Y)
  1008.     end
  1009.     TFGen.Editor.Pos = pos
  1010.     TFGen.Editor.UpdateUI()
  1011. end
  1012. function TFGen.Editor.ChangeIndex(step)             -- Positive number to go next, negative number to go back, always loop
  1013.     TFGen.CurrentGlyphIndex = ((TFGen.CurrentGlyphIndex - 1) + step) % #TFGen.Glyph + 1
  1014.     TFGen.Editor.UpdateUI()
  1015. end
  1016. function TFGen.Editor.UpdateUI()                    -- Fresh UI
  1017.     if( TFGen.CurrentGlyphIndex > 0 and TFGen.CurrentGlyphIndex <= #TFGen.Glyph ) then
  1018.         local currentGlyph = TFGen.Glyph[TFGen.CurrentGlyphIndex]
  1019.         if( string.len(currentGlyph.Char) > 0 ) then
  1020.             TFGen.Editor.Cons.charBtn   :text( "Char: [ "..currentGlyph.Char.." ]" )
  1021.         else
  1022.             TFGen.Editor.Cons.charBtn   :text( "Char: []" )
  1023.         end
  1024.         TFGen.Editor.Cons.mTopBtn   :text( tostring(currentGlyph.Margin.Top  ) )
  1025.         TFGen.Editor.Cons.mLeftBtn  :text( tostring(currentGlyph.Margin.Left ) )
  1026.         TFGen.Editor.Cons.mRightBtn :text( tostring(currentGlyph.Margin.Right) )
  1027.     end
  1028. end
  1029. function TFGen.Editor.SaveFontToFile(glyphList, cachedStr)
  1030.     local fontStr = {}
  1031.     if( cachedStr ~= nil and string.len(cachedStr) > 0 ) then
  1032.         fontStr = cachedStr
  1033.     else
  1034.         local fontHead = "\n--- Font Generated by TFGen ---\n"
  1035.         fontHead = fontHead.."\nif(Texter._Fontmatrix == nil) then Texter._Fontmatrix = {} end"
  1036.         fontHead = fontHead.."\nTexter._Fontmatrix[\""..glyphList.Name.."\"] = {"
  1037.         table.insert( fontStr, "\n\tHeight = "..glyphList.Height )  -- Height
  1038.         local glyphStr = {}
  1039.         for i, glyph in ipairs(glyphList) do
  1040.             glyphStr = {}
  1041.             local char   = "nil"
  1042.             local mtx    = {}
  1043.             if(string.len(glyph.Char) > 0) then
  1044.                 char = string.gsub(glyph.Char, "[\\\"]", "\\%1")
  1045.             end
  1046.             -- Space is no need to save it's matrix, just save the width is ok.
  1047.             if( char ~= " " ) then
  1048.                 -- Generate mtx str ... as long as it's not a space
  1049.                 for j = 1, #glyph.Mtx do
  1050.                     for k = 1, #glyph.Mtx[j] do
  1051.                         local particle = glyph.Mtx[j][k]
  1052.                         -- Save ptype
  1053.                         if( (particle.ptype ~= 0) and ((bit.bor(glyphList.Mode, 0) == 0) or (bit.band(glyphList.Mode, 1) ~= 1)) ) then
  1054.                             particle.ptype = 1
  1055.                         end
  1056.                         -- Save dcolor
  1057.                         if( (particle.ptype == 0) or (bit.bor(glyphList.Mode, 0) == 0) or (bit.band(glyphList.Mode, 2) ~= 2) ) then
  1058.                             particle.dcolor = 0
  1059.                         end
  1060.                         if( particle.dcolor == 0 ) then
  1061.                             glyph.Mtx[j][k] = particle.ptype
  1062.                         else
  1063.                             -- 0xAARRGGBBTT, TT is ptype in Hex, AARRGGBB is dcolor
  1064.                             glyph.Mtx[j][k] = "0x"..string.format("%X", particle.dcolor)..string.format("%X", particle.ptype)
  1065.                         end
  1066.                     end
  1067.                     table.insert( mtx, "{"..table.concat(glyph.Mtx[j], ",").."}" )
  1068.                 end
  1069.                 table.insert( glyphStr, "\n\t\tMtx = {\n\t\t\t"..table.concat(mtx, ",\n\t\t\t").."\n\t\t}" ) -- Matrix
  1070.             end
  1071.            
  1072.             if(glyph.Margin ~= nil and bit.bor(glyph.Margin.Top, glyph.Margin.Left, glyph.Margin.Right) ~= 0)then
  1073.                 marginStr = {} -- Margin
  1074.                 if(glyph.Margin.Top   ~= 0)then table.insert( marginStr, "\n\t\t\tTop   = "..glyph.Margin.Top   ) end
  1075.                 if(glyph.Margin.Left  ~= 0)then table.insert( marginStr, "\n\t\t\tLeft  = "..glyph.Margin.Left  ) end
  1076.                 if(glyph.Margin.Right ~= 0)then table.insert( marginStr, "\n\t\t\tRight = "..glyph.Margin.Right ) end
  1077.                 table.insert( glyphStr, "\n\t\tMargin = {"..table.concat(marginStr, ",").."\n\t\t}" )
  1078.             end
  1079.             table.insert( fontStr, "\n\t[\""..char.."\"] = {"..table.concat(glyphStr, ",").."\n\t}" ) -- Glyph
  1080.         end
  1081.         fontStr = fontHead..table.concat(fontStr, ",").."\n}"
  1082.     end
  1083.     local fontFileName = glyphList.Name..".texterfont"
  1084.     local file = io.open(fontFileName, "w")
  1085.     if file then
  1086.         file:write(fontStr)
  1087.         file:close()
  1088.         local shouldMove = ""
  1089.         if( Texter ~= nil and Texter.FONT_FOLDERS_TO_LOAD ~= nil ) then
  1090.             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")
  1091.         else
  1092.             tpt.message_box("File saved", "Font file \""..fontFileName.."\"\nsaved to game dir, please move it to\nthe font folder.")
  1093.         end
  1094.         if( shouldMove == "Yes" ) then
  1095.             TFGen.Editor.MoveFontToFontDir(".", Texter.FONT_FOLDERS_TO_LOAD, fontFileName)
  1096.         end
  1097.         Texter.Init(false)
  1098.     else
  1099.         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")
  1100.         if( shouldTryAgain == "Yes" ) then
  1101.             TFGen.Editor.SaveFontToFile(glyph, fontStr) -- Try again
  1102.         end
  1103.     end
  1104. end
  1105. function TFGen.Editor.MoveFontToFontDir(rootPath, foldersToLoad, fontFileName)
  1106.     local fontFolder = TFGen.Editor.FindDeepestFontFolder(rootPath, foldersToLoad, Texter.FONT_SEARCH_DEPTH)
  1107.     local success = false
  1108.     if( fontFolder~= nil and string.len(fontFolder) > 0 or foldersToLoad["."] ~= nil ) then -- If . is available, no need to move
  1109.         success = fileSystem.move(fontFileName, fontFolder.."\\"..fontFileName)
  1110.     end
  1111.     if( not success ) then
  1112.         tpt.message_box("Move font faild", "Sorry, font file \""..fontFileName.."\"\nfailed to move :(\nPlease move it to \""..fontFolder.."\".")
  1113.     end
  1114. end
  1115. function TFGen.Editor.FindDeepestFontFolder(rootPath, foldersToLoad, depth) -- But not the root folder
  1116.     if(  rootPath == nil  ) then
  1117.         rootPath = "."
  1118.     end
  1119.     if(  depth == nil  ) then
  1120.         depth = 1
  1121.     end
  1122.     local fontFolder = nil
  1123.     for i, folderName in ipairs(foldersToLoad) do
  1124.         if( string.match(rootPath, "\\?"..folderName.."$") ~= nil and rootPath ~= ".") then
  1125.             fontFolder = rootPath -- If it's the folder we look for
  1126.             break
  1127.         end
  1128.     end
  1129.     -- Let's check the subs for deepest one ( by overwrite fontFolder )
  1130.     if(  depth > 0  ) then
  1131.         local subs = fs.list(rootPath)
  1132.         local subFontFolder = nil
  1133.         for i=1, #subs do
  1134.             if( Texter._IsFolder(rootPath.."\\"..subs[i]) ) then
  1135.                 subFontFolder = TFGen.Editor.FindDeepestFontFolder(rootPath.."\\"..subs[i], foldersToLoad, depth - 1)
  1136.             end
  1137.             if( subFontFolder ~= nil and string.len(subFontFolder) > 0 ) then  -- Cheers!
  1138.                 fontFolder = subFontFolder
  1139.                 break
  1140.             end
  1141.         end
  1142.     end
  1143.     return fontFolder
  1144. end
  1145.  
  1146. TFGen.Init()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement