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