UI Text

From GiderosMobile
Revision as of 12:32, 8 December 2019 by MoKaLux (talk | contribs)


Here you will find various resources to help you create texts in Gideros Studio.


note:You may have to provide your own assets (fonts, gfx, …).

Text Wrap @Gideros Wiki

-- TEXT WRAP FROM GIDEROS WIKI
local mystring = "Some very long text. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, ultricies sed, dolor."
local textfield = TextField.new(nil, mystring)
textfield:setScale(2)
textfield:setSample(mystring)
textfield:setLayout( {w=144, h=100, lineSpacing=7, flags=FontBase.TLF_CENTER} )
textfield:setPosition(8, 16)
stage:addChild(textfield)

TextBox @antix

Textbox.png

-- @antix
TextBox = Core.class(Sprite)

function TextBox:init(options)
	-- default options
	local props = {
		x	= 0,
		y	= 0,
		width = 256, -- constrain width of TextBox to this
		linePadding = 3, -- pixel gap between text lines
		color = 0xe0e0e0, -- default text color
		font = Font:getDefault(),
		text = "",
	}

	-- overwrite default options
	if options then
		for key, value in pairs(options) do
			props[key]= value
		end
	end
	self.props = props

	-- we only need one actual TextField that we will reuse to render our TextBox
	local brush = TextField.new(props.font, "")
	self.brush = brush
	self:redraw()
end

-- set new text and redraw
function TextBox:setText(text)
	local props = self.props
	props.text = text
	self:redraw()
end

-- set new font and redraw
function TextBox:setFont(font)
	local props = self.props
	props.font = font
	self:redraw()
end

-- redraw the textbox
function TextBox:redraw()
	local props = self.props
	local font = props.font

	-- discard any previous imagery
	if self:getNumChildren() > 0 then
		self:removeChildAt(1)
	end

	-- calculate various offsets
	local lineHeight = font:getLineHeight()
	local actualHeight = lineHeight + props.linePadding
	self.lineHeight = lineHeight
	self.actualHeight = actualHeight

	-- split and format text
	local lines = self:splitText(props.text, font, props.width)
	self.lines = lines

	-- create a blank canvas where we will render our text
	local canvas = RenderTarget.new(props.width, (#lines + 1) * actualHeight)
	self.canvas = canvas

	local brush = self.brush
	-- render text to canvas
	for i = 1, #lines do
		local line = lines[i]
		local words = line.words
		for w = 1, #words do
			local word = words[w]
			brush:setText(word.word)
			brush:setTextColor(word.color)
			brush:setPosition(word.x + line.x, i * actualHeight)
			canvas:draw(brush)
			--print(string.format("word=%s, x=%d, 0x%06x", word.word, word.x, word.color))
		end
	end

	-- create bitmap to display
	local bitmap = Bitmap.new(canvas) -- our canvas is the texture)
	bitmap:setPosition(props.x, props.y)

	self:addChild(bitmap)
end

-- recolor a single matching string text or all matching text if "all = true"
function TextBox:recolor(text, color, all)
	local brush = self.brush
	local canvas = self.canvas

	local lineHeight = self.lineHeight
	local actualHeight = self.actualHeight

	local lines = self.lines
	for i = 1, #lines do
		local line = lines[i]
		local words = line.words
		for j = 1, #words do
			local word = words[j]
			if word.word == text then
				canvas:clear(0x000000, 0, word.x + line.x, i * actualHeight - lineHeight, word.width, actualHeight) -- clear area where word was
				word.color = color
				brush:setText(word.word)
				brush:setTextColor(color)
				brush:setPosition(word.x + line.x, i * actualHeight)
				canvas:draw(brush) -- draw word
				if not all then
					return
				end
			end
		end
	end
end

-- this does the heavy lifting, splitting and formatting text lines and words
function TextBox:splitText(text, font, maxWidth)
	local props = self.props

	local spaceWidth = font:getAdvanceX(" ")

	local words = {}
	local lines = {}
	local wordList = {}

	-- split text into words (space separated)
	local smatch = string.gmatch
	local pattern = '([^ ]+)'
	for str in smatch(text, pattern) do
		words[#words + 1] = str
	end

	local i = 1 -- which word we are currently processing
	local x = 0 -- the x offset for any line of text
	local lineWidth = 0 -- total width of text in pixels
	local color = props.color -- initial color
	local align = "left" -- current alignment
	local line = ""

	local function newLine()
		-- calculate offset for aligned text
		if align == "left" then
			x = 0
		elseif align == "right" then
			x = maxWidth - lineWidth
		elseif align == "center" then
			x = (maxWidth * 0.5) - (lineWidth * 0.5)
		end
		
		lines[#lines + 1] = {
			color = color,
			text = line,
			align = align,
			width = font:getAdvanceX(line),
			words = wordList,
			x = x,
		}

		lineWidth = 0
		line = ""
		wordList = {}
		i = i + 1
	end

	local done = false
	repeat
		local word = words[i]

		if word == "#n#" then
			-- process line feed
			newLine()
		elseif word == "#color#" then
			-- process text color change
			color = tonumber(words[i + 1])
			i = i + 2
		elseif word == "#align#" then
			-- process text alignment
			align = words[i + 1]
			i = i + 2
		else
			-- process a normal word
			local wordWidth = font:getAdvanceX(word)

			local w = {
				word = word,
				width = wordWidth,
				x = lineWidth,
				color = color,
			}

			if lineWidth + wordWidth + spaceWidth >= maxWidth then
				-- container width exceeded, create a new line but skip back one word because it needs to appear on the next line
				i = i - 1
				newLine()
			else
				-- process word normally
				wordList[#wordList + 1] = w
				line = line .. " " .. word
				lineWidth = lineWidth + wordWidth + spaceWidth
				i = i + 1
			end
		end

		if i > #words then
			-- all words processed, append the last line and set exit condition
			newLine()
			done = true
		end
	until done

	return lines
end

--[[
-- USAGE
local textBox = TextBox.new(
	{
	  text = "This is a TextBox. It contains text that is automatically split into multiple lines"..
		" and of course every #color# 0x0066ff word #color# 0x33ff55 can #color# 0x33ffff be"..
		" #color# 0xff66ff individually #color# 0x00ff00 colored."..
		" #color# 0xffffff Then there are line breaks which make life..."..
		" #n# #n# so much easier!!!"..
		" #n# #n# #color# 0xf00000 #align# right Lets align the text to the right #n#"..
		" It looks pretty good this way #n# #n# #align# center #color# 0x4080d0 but centered text #n# is always good"..
		" also #n# #n# #color# 0xf0f0f0 #align# left Well that's a wrap :)",
	}
)
stage:addChild(textBox)
-- recolor all occurences of "is" to the color magenta
textBox:recolor("is", 0xff00ff, true)
-- recolor the first occurence of "the" to the color cyan
textBox:recolor("the", 0x00ffff)
]]

Typewriter Style @koeosstudio

-- @koeosstudio
console = Core.class(Sprite)

function console:init()
	local fnt = TTFont.new("Assets/arial.ttf", 20)
	self.txt = TextField.new(fnt, nil)
	self.txt:setLayout({w = 300, flags=FontBase.TLF_LEFT})
	self.txt:setAnchorPoint(0, 0)
	self:addChild(self.txt)
	self.allowType = true

	-- Simple scroll function
	local z = nil
	self:addEventListener(Event.MOUSE_DOWN, function (event)
		z = event.y - self.txt:getY()
	end)
	self:addEventListener(Event.MOUSE_MOVE, function (event)
		self.txt:setY(event.y - z)
	end)
end

function console:tWrite(txtToPrint)
	if self.allowType then
		self.allowType = false
		local i = 1
		self.txt:setText(self.txt:getText()..'\n')

		local function typeFunc()
			self.txt:setText(self.txt:getText()..string.sub(txtToPrint, i, i))
			i = i + 1
			
			if i > string.len(txtToPrint) then
				self.allowType = true
				self:removeEventListener(Event.ENTER_FRAME, typeFunc)
			end
		end

		self:addEventListener(Event.ENTER_FRAME, typeFunc)
	end
end

-- Usage
application:setLogicalDimensions(480, 800)
local myconsole = console.new()
stage:addChild(myconsole)
-- Generate sample txt 
local s = ""
for i = 1, 10 do
	s = s.."TextField with typewriter effect. Drag to Scroll.\n\n"
end
-- Print
myconsole:tWrite(s)