Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • amagad/t-engine4
  • HirumaKai/t-engine4
  • Hogulus/t-engine4
  • Inkie/t-engine4
  • Liberty/t-engine4
  • Lokean/t-engine4
  • Mawootad/t-engine4
  • Michelle/t-engine4
  • MrFrog/t-engine4
  • Nagyhal/t-engine4
  • Recaiden/t-engine4
  • RootOfAllThings/t-engine4
  • Sebsebeleb/t-engine4
  • Sheila/t-engine4
  • Shibari/t-engine4
  • Stof/t-engine4
  • Umbral/t-engine4
  • tome/t-engine4
  • 0player/t-engine4
  • BreezyIdiot/t-engine4
  • Bunny/t-engine4
  • Effigy/t-engine4
  • Hachem_Muche/t-engine4
  • razakai/t-engine4
  • Zireael/t-engine4
  • cinornu/t-engine4
  • edge2054/t-engine4
  • gordaxx727/t-engine4
  • grayswandir/t-engine4
  • helminthauge/t-engine4
  • housepet/t-engine4
  • minqmay/t-engine4
  • nsrr/t-engine4
  • orange/t-engine4
  • otowakotori/t-engine4
  • purequestion/t-engine4
  • rexorcorum/t-engine4
  • rgeens/t-engine4
  • sageacrin/t-engine4
  • stuntofthelitter/t-engine4
  • tiger_eye/t-engine4
  • xelivous/t-engine4
  • yutio888/t-engine4
43 results
Show changes
Showing
with 1337 additions and 141 deletions
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -23,6 +23,7 @@ local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
--- A generic UI button
-- @classmod engine.ui.SubDialog
module(..., package.seeall, class.inherit(Base, Focusable))
title_shadow = true
......@@ -145,14 +146,8 @@ function _M:updateTitle(title)
local title = title
if type(title)=="function" then title = title() end
self.font_bold:setStyle("bold")
local tw, th = self.font_bold:size(title)
local s = core.display.newSurface(tw, th)
s:erase(0, 0, 0, 0)
s:drawColorStringBlended(self.font_bold, title, 0, 0, self.color.r, self.color.g, self.color.b, true)
self.title_tex = self:drawFontLine(self.font_bold, title)
self.font_bold:setStyle("normal")
self.title_tex = {s:glTexture()}
self.title_tex.w = tw
self.title_tex.h = th
end
function _M:loadUI(t)
......@@ -414,8 +409,8 @@ function _M:display(x, y, nb_keyframes)
-- Title
if self.title then
if self.title_shadow then self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2 + 3 + self.frame.title_x, y + 3 + self.frame.title_y, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3], 0, 0, 0, 0.5) end
self.title_tex[1]:toScreenFull(x + (self.w - self.title_tex.w) / 2 + self.frame.title_x, y + self.frame.title_y, self.title_tex.w, self.title_tex.h, self.title_tex[2], self.title_tex[3])
if self.title_shadow then self:textureToScreen(self.title_tex, x + 3 + (self.w - self.title_tex.w) / 2 + self.frame.title_x, y + 3 + self.frame.title_y, 0, 0, 0, 0.5) end
self:textureToScreen(self.title_tex, x + (self.w - self.title_tex.w) / 2 + self.frame.title_x, y + self.frame.title_y)
end
self:innerDisplayBack(x, y, nb_keyframes, tx, ty)
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -21,7 +21,8 @@ require "engine.class"
local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
--- A generic UI list
--- A generic UI surface zone
-- @classmod engine.ui.SurfaceZone
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
......@@ -47,6 +48,10 @@ function _M:generate()
self.can_focus = false
end
function _M:update()
self.s:updateTexture(self.texture)
end
function _M:display(x, y)
if self.text_shadow then self.texture:toScreenFull(x+2, y+2, self.w, self.h, self.texture_w, self.texture_h, 0, 0, 0, self.text_shadow) end
self.texture:toScreenFull(x, y, self.w, self.h, self.texture_w, self.texture_h)
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -21,7 +21,8 @@ require "engine.class"
local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
--- A generic UI textbox
--- A generic UI tab
-- @classmod engine.ui.Tab
module(..., package.seeall, class.inherit(Base, Focusable))
frame_ox1 = -5
......@@ -33,7 +34,7 @@ function _M:init(t)
self.title = assert(t.title, "no tab title")
self.text = t.text or ""
self.selected = t.default
self.fct = assert(t.fct, "no tab fct")
self.fct = t.fct
self.on_change = t.on_change
Base.init(self, t)
......@@ -44,12 +45,8 @@ function _M:generate()
self.key:reset()
-- Draw UI
self.title_w, self.title_h = self.font:size(self.title)
self.w, self.h = self.title_w - frame_ox1 + frame_ox2, self.title_h - frame_oy1 + frame_oy2
local s = core.display.newSurface(self.title_w, self.title_h)
s:drawColorStringBlended(self.font, self.title, 0, 0, 255, 255, 255, true)
self.tex = {s:glTexture()}
self.tex = self:drawFontLine(self.font, self.title)
self.w, self.h = self.tex.w - frame_ox1 + frame_ox2, self.tex.h - frame_oy1 + frame_oy2
-- Add UI controls
self.mouse:registerZone(0, 0, self.w+1, self.h+6, function(button, x, y, xrel, yrel, bx, by, event)
......@@ -58,7 +55,7 @@ function _M:generate()
end
end)
self.rw, self.rh = self.title_w, self.title_h
self.rw, self.rh = self.tex.w, self.tex.h
self.frame = self:makeFrame("ui/button", self.w, self.h)
-- self.frame.b2 = self:getUITexture("ui/border_hor_middle.png")
......@@ -111,6 +108,6 @@ function _M:display(x, y, nb_keyframes)
else
self:drawFrame(self.frame_sel, x, y, 1, 0.5, 0.5, 1)
end
if self.text_shadow then self.tex[1]:toScreenFull(x+1-frame_ox1, y+1-frame_oy1, self.rw, self.rh, self.tex[2], self.tex[3], 0, 0, 0, self.text_shadow) end
self.tex[1]:toScreenFull(x-frame_ox1, y-frame_oy1, self.rw, self.rh, self.tex[2], self.tex[3])
if self.text_shadow then self:textureToScreen(self.tex, x-frame_ox1, y-frame_oy1, 0, 0, 0, self.text_shadow) end
self:textureToScreen(self.tex, x-frame_ox1, y-frame_oy1)
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
local Tab = require "engine.ui.Tab"
local Separator = require "engine.ui.Separator"
local UIGroup = require "engine.ui.UIGroup"
--- A tab container
-- @classmod engine.ui.Tabs
module(..., package.seeall, class.inherit(Base, Focusable, UIGroup))
function _M:init(t)
self.tabs = assert(t.tabs, "no tab tabs")
self.on_change = assert(t.on_change, "no on_change")
self.force_width = t.width
Base.init(self, t)
end
function _M:generate()
self.mouse:reset()
self.key:reset()
self.uis = {}
local cx = 0
for i, tdef in ipairs(self.tabs) do
local kind = tdef.kind
local tab = Tab.new{title=tdef.title, on_change=function() self:select(kind) end}
tab.mouse.delegate_offset_x = cx
tab.mouse.delegate_offset_y = 0
self.uis[#self.uis+1] = {x=cx, y=0, ui=tab}
cx = cx + tab.w
self.h = math.max(tab.h, self.h or 0)
end
self.w = self.force_width or cx
self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
self:mouseEvent(button, x, y, xrel, yrel, bx, by, event)
end)
self:select(self.tabs[1].kind)
end
function _M:mouseEvent(button, x, y, xrel, yrel, bx, by, event)
-- Look for focus
for i = 1, #self.uis do
local ui = self.uis[i]
if ui.ui.can_focus and bx >= ui.x and bx <= ui.x + ui.ui.w and by >= ui.y and by <= ui.y + ui.ui.h then
self:setInnerFocus(i)
-- Pass the event
ui.ui.mouse:delegate(button, bx, by, xrel, yrel, bx, by, event)
return
end
end
self:no_focus()
end
function _M:select(kind)
for i, ui in ipairs(self.uis) do
if self.tabs[i].kind == kind then ui.ui.selected = true
else ui.ui.selected = false
end
end
self.on_change(kind)
end
function _M:display(x, y, nb_keyframes, ox, oy)
self._last_x, _last_y, self._last_ox, self._last_oy = x, y, ox, oy
-- UI elements
for i = 1, #self.uis do
local ui = self.uis[i]
if not ui.hidden then ui.ui:display(x + ui.x, y + ui.y, nb_keyframes, ox + ui.x, oy + ui.y) end
end
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -18,16 +18,15 @@
-- darkgod@te4.org
require "engine.class"
local Base = require "engine.ui.Base"
local WithTitle = require "engine.ui.WithTitle"
local Focusable = require "engine.ui.Focusable"
--- A generic UI textbox
module(..., package.seeall, class.inherit(Base, Focusable))
-- @classmod engine.ui.Textbox
module(..., package.seeall, class.inherit(WithTitle, Focusable))
function _M:init(t)
self.title = assert(t.title, "no textbox title")
self.text = t.text or ""
self.size_title = t.size_title or t.title
self.old_text = self.text
self.on_mouse = t.on_mouse
self.hide = t.hide
......@@ -42,7 +41,7 @@ function _M:init(t)
self.cursor = #self.tmp + 1
self.scroll = 1
Base.init(self, t)
WithTitle.init(self, t)
end
function _M:on_focus(v)
......@@ -52,34 +51,33 @@ end
function _M:generate()
self.mouse:reset()
self.key:reset()
-- Draw UI
local title_w = self.font:size(self.size_title)
self.title_w = title_w
local frame_w = self.chars * self.font_mono_w + 12
self.w = title_w + frame_w
self.h = self.font_h + 6
self:generateTitle()
local title_w = self.title_w
local font_height = self.font_mono:height()
local fw, fh = self.chars * self.font_mono_w, font_height
-- the following constants are to account for empty pixels on the frames
local ew, eh = 2, 2
local frame = self:makeFrame("ui/textbox", nil, nil, fw - 2 * ew, fh - 2 * eh)
self.frame = frame
self.frame_sel = self:makeFrame("ui/textbox-sel", nil, nil, fw - 2 * ew, fh - 2 * eh)
self.w = title_w + frame.w
self.h = frame.h
self.texcursor = self:getUITexture("ui/textbox-cursor.png")
self.frame = self:makeFrame("ui/textbox", frame_w, self.h)
self.frame_sel = self:makeFrame("ui/textbox-sel", frame_w, self.h)
local b2, b8, b4, b6 = frame.b2.h, frame.b8.h, frame.b4.w, frame.b6.w
local w, h = self.w, self.h
local fw, fh = frame_w - 12, self.font_h
self.fw, self.fh = fw, fh
self.text_x = 6 + title_w
self.text_y = (h - fh) / 2
self.cursor_y = (h - self.texcursor.h) / 2
self.max_display = math.floor(fw / self.font_mono_w)
self.text_surf = core.display.newSurface(fw, fh)
self.text_tex, self.text_tex_w, self.text_tex_h = self.text_surf:glTexture()
self.text_x = b4 - ew + title_w
self.text_y = b8 - eh
self.title_y = self.text_y + self.font_mono:lineSkip() - self.font:lineSkip() -- align baselines
self.max_display = self.chars
self:updateText()
if title_w > 0 then
local s = core.display.newSurface(title_w, h)
s:erase(0, 0, 0, 0)
s:drawColorStringBlended(self.font, self.title, 0, (h - fh) / 2, 255, 255, 255, true)
self.tex, self.tex_w, self.tex_h = s:glTexture()
self.tex = self:drawFontLine(self.font, self.title, title_w)
end
-- Add UI controls
......@@ -100,17 +98,23 @@ function _M:generate()
self.key:addCommands{
_LEFT = function() self.cursor = util.bound(self.cursor - 1, 1, #self.tmp+1) self.scroll = util.scroll(self.cursor, self.scroll, self.max_display) self:updateText() end,
_RIGHT = function() self.cursor = util.bound(self.cursor + 1, 1, #self.tmp+1) self.scroll = util.scroll(self.cursor, self.scroll, self.max_display) self:updateText() end,
_DELETE = function()
if self.cursor <= #self.tmp then
table.remove(self.tmp, self.cursor)
_BACKSPACE = function()
if self.cursor > 1 then
local st = core.key.modState("ctrl") and 1 or self.cursor - 1
for i = self.cursor - 1, st, -1 do
table.remove(self.tmp, i)
self.cursor = self.cursor - 1
self.scroll = util.scroll(self.cursor, self.scroll, self.max_display)
end
self:updateText()
end
end,
_BACKSPACE = function()
if self.cursor > 1 then
table.remove(self.tmp, self.cursor - 1)
self.cursor = self.cursor - 1
self.scroll = util.scroll(self.cursor, self.scroll, self.max_display)
_DELETE = function()
if self.cursor <= #self.tmp then
local num = core.key.modState("ctrl") and #self.tmp - self.cursor + 1 or 1
for i = 1, num do
table.remove(self.tmp, self.cursor)
end
self:updateText()
end
end,
......@@ -147,6 +151,10 @@ function _M:generate()
self:updateText()
end
end,
[{"_c", "ctrl"}] = function(c)
self:updateText()
core.key.setClipboard(self.text)
end,
}
end
......@@ -162,28 +170,25 @@ end
function _M:updateText()
if not self.tmp[1] then self.tmp = {} end
self.text = table.concat(self.tmp)
local text = ""
for i = self.scroll, self.scroll + self.max_display - 1 do
if not self.tmp[i] then break end
if not self.hide then text = text .. self.tmp[i]
else text = text .. "*" end
end
local text
local b, e = self.scroll, math.min(self.scroll + self.max_display - 1, #self.tmp)
if not self.hide then text = table.concat(self.tmp, nil, b, e)
else text = string.rep("*", e - b + 1) end
self.text_tex = self:drawFontLine(self.font_mono, text, self.fw)
self.text_surf:erase(0, 0, 0, 0)
self.text_surf:drawStringBlended(self.font_mono, text, 0, 0, 255, 255, 255, true)
self.text_surf:updateTexture(self.text_tex)
if self.on_change and self.old_text ~= self.text then self.on_change(self.text) end
self.old_text = self.text
end
function _M:display(x, y, nb_keyframes)
if self.tex then
if self.text_shadow then self.tex:toScreenFull(x+1, y+1, self.title_w, self.h, self.tex_w, self.tex_h, 0, 0, 0, self.text_shadow) end
self.tex:toScreenFull(x, y, self.title_w, self.h, self.tex_w, self.tex_h)
end
local text_x, text_y = self.text_x, self.text_y
self:displayTitle(x, y, nb_keyframes)
if self.focused then
self:drawFrame(self.frame_sel, x + self.title_w, y)
self.texcursor.t:toScreenFull(x + self.text_x + (self.cursor-self.scroll) * self.font_mono_w, y + self.cursor_y, self.texcursor.w, self.texcursor.h, self.texcursor.tw, self.texcursor.th)
local cursor_x = self.font_mono:size(self.text:sub(self.scroll, self.cursor - 1))
self.texcursor.t:toScreenFull(x + self.text_x + cursor_x - (self.texcursor.w / 2) + 2, y + text_y + 5,
self.texcursor.w, self.fh - 7, self.texcursor.tw, self.texcursor.th)
else
self:drawFrame(self.frame, x + self.title_w, y)
if self.focus_decay then
......@@ -192,6 +197,6 @@ function _M:display(x, y, nb_keyframes)
if self.focus_decay <= 0 then self.focus_decay = nil end
end
end
if self.text_shadow then self.text_tex:toScreenFull(x+1 + self.text_x, y+1 + self.text_y, self.fw, self.fh, self.text_tex_w, self.text_tex_h, 0, 0, 0, self.text_shadow) end
self.text_tex:toScreenFull(x + self.text_x, y + self.text_y, self.fw, self.fh, self.text_tex_w, self.text_tex_h)
if self.text_shadow then self:textureToScreen(self.text_tex, x+1 + self.text_x, y+1 + self.text_y, 0, 0, 0, self.text_shadow) end
self:textureToScreen(self.text_tex, x+1 + self.text_x, y+1 + self.text_y)
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -22,7 +22,8 @@ local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
local Slider = require "engine.ui.Slider"
--- A generic UI list
--- A generic UI text zone
-- @classmod engine.ui.Textzone
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
......@@ -36,8 +37,9 @@ function _M:init(t)
self.scrollbar = t.scrollbar
self.auto_height = t.auto_height
self.auto_width = t.auto_width
self.has_box = t.has_box
self.fct = t.fct
self.dest_area = t.dest_area and t.dest_area or { h = self.h }
self.color = t.color or {r=255, g=255, b=255}
......@@ -71,6 +73,11 @@ function _M:generate()
if self.scrollbar then self.scrollbar.max=self.max_display - self.h end
if self.has_box then
self.frame = self:makeFrame("ui/textbox", nil, nil, self.w, self.h)
self.frame_ox, self.frame_oy = self.frame.b4.w, self.frame.b8.h
end
-- Add UI controls
self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
if self.fct and button == "left" and event == "button" then self.fct() end
......@@ -105,12 +112,19 @@ function _M:generate()
}
end
function _M:setShadowShader(shader, power)
self.shadow_shader = shader
self.shadow_power = power
end
function _M:display(x, y, nb_keyframes, screen_x, screen_y, offset_x, offset_y, local_x, local_y)
if not self.list then return end
offset_x = offset_x and offset_x or 0
offset_y = (offset_y and offset_y) or (self.scrollbar and self.scrollbar.pos or 0)
local_x = local_x and local_x or 0
local_y = local_y and local_y or 0
local shader = self.shadow_shader
local loffset_y = offset_y - local_y
local current_y = 0
......@@ -118,6 +132,10 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y, offset_x, offset_y,
local total_h = 0
local clip_y_start = 0
local clip_y_end = 0
if self.frame then
self:drawFrame(self.frame, x - self.frame_ox, y - self.frame_oy)
end
if self.scrollbar then
self.scrollbar.pos = util.minBound(self.scrollbar.pos + self.scroll_inertia, 0, self.scrollbar.max)
......@@ -152,13 +170,22 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y, offset_x, offset_y,
end
local one_by_tex_h = 1 / item._tex_h
if self.text_shadow then item._tex:toScreenPrecise(x + current_x + 1, y + current_y + 1, item.w, item.h - (clip_y_start + clip_y_end), 0, item.w / item._tex_w, clip_y_start * one_by_tex_h, (item.h - clip_y_end) * one_by_tex_h, 0, 0, 0, self.text_shadow) end
if self.text_shadow then
if shader then
shader:use(true)
shader:uniOutlineSize(self.shadow_power, self.shadow_power)
shader:uniTextSize(item._tex_w, item._tex_h)
else
item._tex:toScreenPrecise(x + current_x + 1, y + current_y + 1, item.w, item.h - (clip_y_start + clip_y_end), 0, item.w / item._tex_w, clip_y_start * one_by_tex_h, (item.h - clip_y_end) * one_by_tex_h, 0, 0, 0, self.text_shadow)
end
end
item._tex:toScreenPrecise(x + current_x, y + current_y, item.w, item.h - (clip_y_start + clip_y_end), 0, item.w / item._tex_w, clip_y_start * one_by_tex_h, (item.h - clip_y_end) * one_by_tex_h )
if self.text_shadow and shader then shader:use(false) end
-- add only visible part of item
current_y = current_y + item.h - clip_y_start
current_y = current_y + self.font_h - clip_y_start
end
-- add full size of item
total_h = total_h + item.h
total_h = total_h + self.font_h
-- if we are too deep then end this
if total_h > loffset_y + self.dest_area.h then break end
end
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -23,7 +23,8 @@ local Focusable = require "engine.ui.Focusable"
local Slider = require "engine.ui.Slider"
local Separator = require "engine.ui.Separator"
--- A generic UI list
--- A generic UI textzone list
-- @classmod engine.ui.TextzoneList
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
......@@ -35,7 +36,8 @@ function _M:init(t)
self.scrollbar = t.scrollbar
self.focus_check = t.focus_check
self.variable_height = t.variable_height
self.pingpong = t.pingpong and 0
self.scroll_delay = t.pingpong
self.dest_area = t.dest_area and t.dest_area or { h = self.h }
self.max_h = 0
self.scroll_inertia = 0
......@@ -154,6 +156,10 @@ function _M:switchItem(item, create_if_needed, force)
self.list = d.list
self.max_display = d.max_display
self.cur_item = item
if self.pingpong then
self.pingpong = 0
self.pingpong_last = nil
end
return true
end
......@@ -180,6 +186,34 @@ function _M:display(x, y, nb_keyframes, ox, oy, offset_x, offset_y, local_x, loc
elseif self.scroll_inertia < 0 then self.scroll_inertia = math.min(self.scroll_inertia + 1, 0)
end
if self.scrollbar.pos == 0 or self.scrollbar.pos == self.scrollbar.max then self.scroll_inertia = 0 end
if self.pingpong and not self.focused then
local time = core.game.getTime()
if not self.pingpong_last then self.pingpong_last = time + self.scroll_delay * self.h / 3 end
local delta = math.max(time - self.pingpong_last, 0) / self.scroll_delay
local scrollbar = self.scrollbar
if delta > 0 and scrollbar.max > 0 then
local slowdown = 0.5 * scrollbar.pos / scrollbar.max
self.pingpong_last = time
if self.pingpong == 0 then
scrollbar.pos = scrollbar.pos + delta * (0.5 + slowdown)
if scrollbar.pos >= scrollbar.max then
scrollbar.pos = scrollbar.max
self.pingpong = 1
self.pingpong_last = time + self.scroll_delay * self.h / 3
end
else
-- scroll back twice as fast, since it's awkward to read during that time
scrollbar.pos = scrollbar.pos - delta * 2
if scrollbar.pos <= 0 then
scrollbar.pos = 0
self.pingpong = 0
self.pingpong_last = time + self.scroll_delay * self.h / 3
end
end
end
end
end
local loffset_y = offset_y - local_y
......@@ -194,6 +228,7 @@ function _M:display(x, y, nb_keyframes, ox, oy, offset_x, offset_y, local_x, loc
clip_y_end = 0
local item_h = item.is_separator and (self.fh - self.sep.h) or item.h
local item_skip = item.is_separator and (self.fh - self.sep.h) or self.font_h
-- if item is within visible area bounds
if total_h + item_h > loffset_y and total_h < loffset_y + self.dest_area.h then
-- if it started before visible area then compute its top clip
......@@ -208,17 +243,17 @@ function _M:display(x, y, nb_keyframes, ox, oy, offset_x, offset_y, local_x, loc
core.display.drawQuad(x + current_x, y + current_y, item._tex_w, item_h - (clip_y_start + clip_y_end), item.background[1], item.background[2], item.background[3], item.background[4])
end
if item.is_separator then
self.sep:display(x + current_x, y + current_y + (self.fh - self.sep.h) * 0.5 - clip_y_start, nb_keyframes, ox, oy, 0, total_h + (self.fh - self.sep.h) * 0.5, 0, loffset_y, self.dest_area)
self.sep:display(x + current_x, y + current_y + (self.fh - self.sep.h) * 0.5, nb_keyframes)
else
local one_by_tex_h = 1 / item._tex_h
if self.text_shadow then item._tex:toScreenPrecise(x + current_x + 1, y + current_y + 1, item.w, item_h - (clip_y_start + clip_y_end), 0, item.w / item._tex_w, clip_y_start * one_by_tex_h, (item_h - clip_y_end) * one_by_tex_h, 0, 0, 0, self.text_shadow) end
item._tex:toScreenPrecise(x + current_x, y + current_y, item.w, item_h - (clip_y_start + clip_y_end), 0, item.w / item._tex_w, clip_y_start * one_by_tex_h, (item_h - clip_y_end) * one_by_tex_h )
end
-- add only visible part of item
current_y = current_y + item_h - clip_y_start
current_y = current_y + item_skip - clip_y_start
end
-- add full size of item
total_h = total_h + item_h
-- add line skip of item
total_h = total_h + item_skip
-- if we are too deep then end this
if total_h > loffset_y + self.dest_area.h then break end
end
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -22,7 +22,8 @@ local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
local Slider = require "engine.ui.Slider"
--- A generic UI list
--- A generic UI tree list
-- @classmod engine.ui.TreeList
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
......@@ -48,8 +49,13 @@ function _M:init(t)
self.plus = _M:getUITexture("ui/plus.png")
self.minus = _M:getUITexture("ui/minus.png")
-- Draw the scrollbar
if self.scrollbar then
self.scrollbar = Slider.new{size=self.h, max=1}
end
local w = self.w
if self.scrollbar then w = w - 10 end
if self.scrollbar then w = w - self.scrollbar.w end
local colw = 0
for j, col in ipairs(self.columns) do
if type(col.width) == "table" then
......@@ -108,8 +114,10 @@ function _M:drawItem(item, nb_keyframes)
local s = col.surface
local offset = 0
item.offset_x = 0
if i == 1 then
offset = level * self.level_offset
item.offset_x = level * self.level_offset
if item.nodes then offset = offset + self.plus.w end
end
local startx = col.frame_sel.b4.w + offset
......@@ -117,6 +125,9 @@ function _M:drawItem(item, nb_keyframes)
item.cols[i] = {}
s:erase(0, 0, 0, 0)
if self.on_drawitem then startx = self.on_drawitem(item, s, startx, self.fh) end
local test_text = text:toString()
local font_w, _ = self.font:size(test_text)
font_w = font_w + startx
......@@ -150,7 +161,6 @@ function _M:drawItem(item, nb_keyframes)
item.cols[i]._tex, item.cols[i]._tex_w, item.cols[i]._tex_h = s:glTexture()
end
end
if self.on_drawitem then self.on_drawitem(item) end
end
function _M:drawTree()
......@@ -176,11 +186,6 @@ function _M:generate()
self.max_display = math.floor(self.h / fh)
-- Draw the scrollbar
if self.scrollbar then
self.scrollbar = Slider.new{size=self.h - fh, max=1}
end
-- Draw the tree items
self:drawTree()
......@@ -269,6 +274,7 @@ function _M:outputList()
self.max = #self.list
self.sel = util.bound(self.sel or 1, 1, self.max)
self.max_display = math.min(math.floor(self.h/self.fh), self.max)
self.scroll = self.scroll or 1
self.cur_col = self.cur_col or 1
end
......@@ -348,7 +354,7 @@ function _M:display(x, y, nb_keyframes)
if item.nodes and j == 1 then
local s = item.shown and self.minus or self.plus
s.t:toScreenFull(x, y + (self.fh - s.h) / 2, s.w, s.h, s.th, s.th)
s.t:toScreenFull(x + item.offset_x, y + (self.fh - s.h) / 2, s.w, s.h, s.th, s.th)
end
x = x + col.width
......@@ -357,8 +363,8 @@ function _M:display(x, y, nb_keyframes)
end
if self.focused and self.scrollbar then
self.scrollbar.pos = self.sel
self.scrollbar.max = self.max
self.scrollbar.pos = self.sel - 1
self.scrollbar.max = self.max - 1
self.scrollbar:display(bx + self.w - self.scrollbar.w, by, by + self.fh)
end
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -22,7 +22,8 @@ local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
local Slider = require "engine.ui.Slider"
--- A generic UI list
--- A generic UI Container
-- @classmod engine.ui.UIContainer
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
......@@ -106,6 +107,7 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y, offset_x, offset_y,
local first = true
for i=1, #self.uis do
ui = self.uis[i]
ui.dest_area = ui.dest_area or {}
ui.dest_area.h = self.dest_area.h
if offset_y <= total_h + self.uis[i].h then
ui:display(x, current_y, nb_keyframes, x, current_y, offset_x, offset_y, local_x, local_y)
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -19,7 +19,8 @@
require "engine.class"
--- Make a UI element clickable
--- A generic UI group
-- @classmod engine.ui.UIGroup
module(..., package.seeall, class.make)
function _M:setInnerFocus(id)
......
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -20,15 +20,22 @@
require "engine.class"
local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
local Slider = require "engine.ui.Slider"
--- A generic UI list
--- A generic UI variable list
-- @classmod engine.ui.VariableList
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
self.list = assert(t.list, "no list list")
self.w = assert(t.width, "no list width")
self.max_h = t.max_height
self.fct = t.fct
self.select = t.select
self.direct_draw = t.direct_draw
self.scrollbar = t.scrollbar
self.all_clicks = t.all_clicks
self.min_items_shown = t.min_items_shown or 3
self.display_prop = t.display_prop or "name"
Base.init(self, t)
......@@ -39,45 +46,79 @@ function _M:generate()
self.key:reset()
self.sel = 1
self.scroll = 1
self.max = #self.list
local fw, fh = self.w, self.font_h
self.fw, self.fh = fw, fh
self.fw = fw, fh
self.frame = self:makeFrame(nil, fw, fh)
self.frame_sel = self:makeFrame("ui/selector-sel", fw, fh)
self.frame_usel = self:makeFrame("ui/selector", fw, fh)
-- Draw the list items
self.h = 0
local sh = 0
local minh = 0
for i, item in ipairs(self.list) do
local color = item.color or {255,255,255}
local text = item[self.display_prop]:splitLines(fw - self.frame_sel.b4.w - self.frame_sel.b6.w, self.font)
local fh = fh * #text + self.frame_sel.b8.w / 3 * 2
local s = core.display.newSurface(fw, fh)
s:erase(0, 0, 0, 0)
local color_r, color_g, color_b = color[1], color[2], color[3]
for z = 1, #text do
color_r, color_g, color_b = s:drawColorStringBlended(self.font, text[z], self.frame_sel.b4.w, self.frame_sel.b8.w / 3 + self.font_h * (z-1), color_r, color_g, color_b, true)
end
local ifh = 0
if not self.direct_draw then
local color = item.color or {255,255,255}
local width = fw - self.frame_sel.b4.w - self.frame_sel.b6.w
local font, fh = self.font, fh
if item.font then
font = item.font
fh = font:lineSkip()
end
item.fh = fh
item._tex = {s:glTexture()}
local text = font:draw(item[self.display_prop], width, color[1], color[2], color[3])
ifh = fh * #text + self.frame_sel.b8.w / 3 * 2
self.mouse:registerZone(0, self.h, self.w, fh, function(button, x, y, xrel, yrel, bx, by, event)
if self.sel and self.list[self.sel] then self.list[self.sel].focus_decay = self.focus_decay_max end
self.sel = i
self:onSelect()
if button == "left" and event == "button" then self:onUse() end
end)
local texs = {}
for z, tex in ipairs(text) do
texs[z] = {t=tex._tex, tw=tex._tex_w, th = tex._tex_h, w=tex.w, h=tex.h, y = (z - 1) * fh + self.frame_sel.b8.w / 3}
end
item.start_h = sh
item.fh = ifh
item._texs = texs
else
ifh = self.direct_draw(item, 0, sh, true)
item.start_h = sh
item.fh = ifh
end
self.h = self.h + fh
sh = sh + ifh
if i <= self.min_items_shown then minh = sh end
end
self.h = math.max(minh, math.min(self.max_h or 1000000, sh))
if sh > self.h then self.scrollbar = true end
self.scroll_inertia = 0
self.scroll = 0
if self.scrollbar then self.scrollbar = Slider.new{size=self.h, max=sh, ui=self.ui} end
self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
self.last_input_was_keyboard = false
if event == "button" and button == "wheelup" then if self.scrollbar then self.scroll_inertia = math.min(self.scroll_inertia, 0) - 5 end
elseif event == "button" and button == "wheeldown" then if self.scrollbar then self.scroll_inertia = math.max(self.scroll_inertia, 0) + 5 end
end
for i = 1, #self.list do
local item = self.list[i]
if by + self.scroll >= item.start_h and by + self.scroll < item.start_h + item.fh then
if self.sel and self.list[self.sel] then self.list[self.sel].focus_decay = self.focus_decay_max end
self.sel = i
self:onSelect()
if (self.all_clicks or button == "left") and event == "button" then self:onUse(button, event) end
break
end
end
end)
-- Add UI controls
self.key:addBinds{
ACCEPT = function() self:onUse() end,
ACCEPT = function() self:onUse("left", "key") end,
MOVE_UP = function()
if self.sel and self.list[self.sel] then self.list[self.sel].focus_decay = self.focus_decay_max end
self.sel = util.boundWrap(self.sel - 1, 1, self.max) self:onSelect()
......@@ -89,22 +130,59 @@ function _M:generate()
}
end
function _M:onUse()
function _M:setList(list)
self.list = list
self:generate()
end
function _M:onUse(button, event)
local item = self.list[self.sel]
if not item then return end
self:sound("button")
if item.fct then item:fct()
else self.fct(item, self.sel) end
if item.fct then item:fct(button, event)
else self.fct(item, self.sel, button, event) end
end
function _M:onSelect()
local item = self.list[self.sel]
if not item then return end
if self.scrollbar then
local pos = 0
for i = 1, #self.list do
local itm = self.list[i]
pos = pos + itm.fh
-- we've reached selected row
if self.sel == i then
-- check if it was visible if not go scroll over there
if pos - itm.fh < self.scrollbar.pos then self.scrollbar.pos = util.minBound(pos - itm.fh, 0, self.scrollbar.max)
elseif pos > self.scrollbar.pos + self.h then self.scrollbar.pos = util.minBound(pos - self.h, 0, self.scrollbar.max)
end
break
end
end
end
if rawget(self, "select") then self.select(item, self.sel) end
end
function _M:display(x, y, nb_keyframes)
function _M:display(x, y, nb_keyframes, screen_x, screen_y)
local by = y
local display_y = 0
core.display.glScissor(true, screen_x, screen_y, self.w, self.h)
if self.scrollbar then
local tmp_pos = self.scrollbar.pos
self.scrollbar.pos = util.minBound(self.scrollbar.pos + self.scroll_inertia, 0, self.scrollbar.max)
if self.scroll_inertia > 0 then self.scroll_inertia = math.max(self.scroll_inertia - 1, 0)
elseif self.scroll_inertia < 0 then self.scroll_inertia = math.min(self.scroll_inertia + 1, 0)
end
if self.scrollbar.pos == 0 or self.scrollbar.pos == self.scrollbar.max then self.scroll_inertia = 0 end
y = y + (self.scrollbar and -self.scrollbar.pos or 0)
self.scroll = self.scrollbar.pos
end
for i = 1, self.max do
local item = self.list[i]
if not item then break end
......@@ -125,8 +203,25 @@ function _M:display(x, y, nb_keyframes)
if item.focus_decay <= 0 then item.focus_decay = nil end
end
end
if self.text_shadow then item._tex[1]:toScreenFull(x+1 + self.frame_sel.b4.w, y+1, self.fw, item.fh, item._tex[2], item._tex[3], 0, 0, 0, self.text_shadow) end
item._tex[1]:toScreenFull(x + self.frame_sel.b4.w, y, self.fw, item.fh, item._tex[2], item._tex[3])
if not self.direct_draw then
for z, tex in pairs(item._texs) do
if self.text_shadow then self:textureToScreen(tex, x+1 + self.frame_sel.b4.w, y+1 + tex.y, 0, 0, 0, self.text_shadow) end
self:textureToScreen(tex, x + self.frame_sel.b4.w, y + tex.y)
end
else
self.direct_draw(item, x + self.frame_sel.b4.w, y)
end
item.last_display_x = screen_x
item.last_display_y = screen_y + display_y
y = y + item.fh
display_y = display_y + item.fh
end
core.display.glScissor(false)
if self.focused and self.scrollbar then
self.scrollbar:display(x + self.w - self.scrollbar.w, by)
self.last_scroll = self.scrollbar.pos
end
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local Base = require "engine.ui.Base"
--- A generic waiter bar
-- @classmod engine.ui.WaitBar
module(..., package.seeall, class.inherit(Base))
function _M:init(t)
self.size = assert(t.size, "no waiter size")
self.text = assert(t.text, "no waiter text")
self.fill = t.fill or 0
self.maxfill = t.maxfill or 100
Base.init(self, t)
end
function _M:updateFill(v, max, text)
self.fill = v
if max then self.maxfill = max end
if text then
self.text = text
self.text_gen = self.font_bold:draw(self.text, self.text:toTString():maxWidth(self.font_bold), 255, 255, 255)[1]
end
end
function _M:generate()
self.t_left = self:getUITexture("ui/waiter/left_basic.png")
self.t_right = self:getUITexture("ui/waiter/right_basic.png")
self.t_middle = self:getUITexture("ui/waiter/middle.png")
self.t_bar = self:getUITexture("ui/waiter/bar.png")
self.w, self.h = self.size + self.t_left.w + self.t_right.w, self.t_left.h
end
function _M:display(x, y)
self.t_middle.t:toScreenFull(x + self.t_left.w, y + (self.t_left.h - self.t_middle.h) / 2, self.size, self.t_middle.h, self.t_middle.tw, self.t_middle.th)
self.t_left.t:toScreenFull(x, y, self.t_left.w, self.t_left.h, self.t_left.tw, self.t_left.th)
self.t_right.t:toScreenFull(x + self.w - self.t_right.w, y, self.t_right.w, self.t_right.h, self.t_right.tw, self.t_right.th)
if self.fill > 0 then
self.t_bar.t:toScreenFull(x + self.t_left.w, y + (self.t_left.h - self.t_bar.h) / 2, self.size * self.fill / self.maxfill, self.t_bar.h, self.t_bar.tw, self.t_bar.th)
end
if self.text_gen then
local item = self.text_gen
item._tex:toScreenFull(2+x + (self.w - item.w) / 2, 2+y + (self.h - item.h) / 2, item.w, item.h, item._tex_w, item._tex_h, 0, 0, 0, 0.7)
item._tex:toScreenFull(x + (self.w - item.w) / 2, y + (self.h - item.h) / 2, item.w, item.h, item._tex_w, item._tex_h, 1, 1, 1, 1)
end
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009, 2010, 2011, 2012 Nicolas Casalini
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
......@@ -20,7 +20,8 @@
require "engine.class"
local Base = require "engine.ui.Base"
--- A generic waiter bar
--- A generic waiter
-- @classmod engine.ui.Waiter
module(..., package.seeall, class.inherit(Base))
function _M:init(t)
......@@ -30,9 +31,20 @@ function _M:init(t)
Base.init(self, t)
end
function _M:manual()
core.wait.enableManualTick(true)
core.display.forceRedraw()
end
function _M:manualStep(nb)
core.wait.manualTick(nb or 1)
end
function _M:generate()
local left = core.display.loadImage("/data/gfx/waiter/left_basic.png")
local right = core.display.loadImage("/data/gfx/waiter/right_basic.png")
self.base_gfx = "/data/gfx/metal-ui"
if fs.exists("/data/gfx/"..Base.ui.."-ui/waiter/left_basic.png") then self.base_gfx = "/data/gfx/"..Base.ui.."-ui" end
local left = core.display.loadImage(self.base_gfx.."/waiter/left_basic.png")
local right = core.display.loadImage(self.base_gfx.."/waiter/right_basic.png")
local lw, lh = left:getSize()
local rw, rh = right:getSize()
self.w, self.h = self.size + lw + lw, lh
......@@ -42,10 +54,20 @@ end
function _M:display(x, y)
end
function _M:setTimeout(secs, cb)
self.timeout_cb = cb
self.timeout = secs * 1000
self.timeout_start = core.game.getTime()
end
function _M:getWaitDisplay(d)
d.__showup = false
d.unload_wait = rawget(d, "unload")
d.unload = function(self) core.wait.disable() if self.unload_wait then self:unload_wait() end end
d.unload = function(self)
core.wait.disable()
if self.unload_wait then self:unload_wait() end
self.unload = rawget(self, "unload_wait")
end
core.display.forceRedraw()
......@@ -55,10 +77,10 @@ function _M:getWaitDisplay(d)
if has_max then core.wait.addMaxTicks(has_max) end
local i, max, dir = 0, has_max or 20, 1
local left = {core.display.loadImage("/data/gfx/waiter/left_basic.png"):glTexture()}
local right = {core.display.loadImage("/data/gfx/waiter/right_basic.png"):glTexture()}
local middle = {core.display.loadImage("/data/gfx/waiter/middle.png"):glTexture()}
local bar = {core.display.loadImage("/data/gfx/waiter/bar.png"):glTexture()}
local left = {core.display.loadImage(self.base_gfx.."/waiter/left_basic.png"):glTexture()}
local right = {core.display.loadImage(self.base_gfx.."/waiter/right_basic.png"):glTexture()}
local middle = {core.display.loadImage(self.base_gfx.."/waiter/middle.png"):glTexture()}
local bar = {core.display.loadImage(self.base_gfx.."/waiter/bar.png"):glTexture()}
return function()
-- Background
......@@ -95,6 +117,11 @@ function _M:getWaitDisplay(d)
txt[1]:toScreenFull(dx + (dw - txt[6]) / 2 + 2, dy + (bar[7] - txt[7]) / 2 + 2, txt[6], txt[7], txt[2], txt[3], 0, 0, 0, 0.6)
txt[1]:toScreenFull(dx + (dw - txt[6]) / 2, dy + (bar[7] - txt[7]) / 2, txt[6], txt[7], txt[2], txt[3])
end
-- Timeout?
if self.timeout and core.game.getTime() - self.timeout_start >= self.timeout then
self.timeout_cb()
end
end
end
end
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
require "engine.class"
local Base = require "engine.ui.Base"
local Focusable = require "engine.ui.Focusable"
--- A web browser
-- @classmod engine.ui.Webview
module(..., package.seeall, class.inherit(Base, Focusable))
function _M:init(t)
self.w = assert(t.width, "no webview width")
self.h = assert(t.height, "no webview height")
self.url = assert(t.url, "no webview url")
self.on_title = t.on_title
self.allow_downloads = t.allow_downloads or {}
self.has_frame = t.has_frame
self.never_clean = t.never_clean
self.allow_popup = t.allow_popup
self.allow_login = t.allow_login
self.custom_calls = t.custom_calls or {}
if self.allow_login == nil then self.allow_login = true end
if self.allow_login and (self.url:find("^http://te4%.org/") or self.url:find("^https://te4%.org/")) and profile.auth then
local param = "_te4ah="..profile.auth.hash.."&_te4ad="..profile.auth.drupid
local first = self.url:find("?", 1, 1)
if first then self.url = self.url.."&"..param
else self.url = self.url.."?"..param end
end
if self.url:find("^http://te4%.org/") or self.url:find("^https://te4%.org/") then
local param = "_te4"
local first = self.url:find("?", 1, 1)
if first then self.url = self.url.."&"..param
else self.url = self.url.."?"..param end
end
print("Creating WebView with url", self.url)
Base.init(self, t)
end
function _M:generate()
self.mouse:reset()
self.key:reset()
if not core.webview then
self.unusable = true
return
end
local handlers = {
on_title = function(title) if self.on_title then self.on_title(title) end end,
on_popup = function(url, w, h) if self.allow_popup then
local Dialog = require "engine.ui.Dialog"
Dialog:webPopup(url, w, h)
end end,
on_loading = function(url, status)
self.cur_url = url
self.loading = status
end,
on_crash = function()
print("WebView crashed, closing C view")
self.view = nil
end,
}
if self.allow_downloads then self:onDownload(handlers) end
self.view = core.webview.new(self.w, self.h, handlers)
if not self.view:usable() then
self.unusable = true
return
end
self.custom_calls.lolzor = function(nb, str)
print("call from js got: ", nb, str)
return "PLAP"
end
self.custom_calls._nextDownloadName = function(name)
if name then self._next_download_name = {name=name, time=os.time()}
else self._next_download_name = nil
end
end
for name, fct in pairs(self.custom_calls) do
handlers[name] = fct
self.view:setMethod(name)
end
self.view:loadURL(self.url)
self.loading = 0
self.loading_rotation = 0
self.scroll_inertia = 0
if self.has_frame then
self.frame = Base:makeFrame("ui/tooltip/", self.w + 8, self.h + 8)
end
self.loading_icon = self:getUITexture("ui/waiter/loading.png")
self.mouse:allowDownEvent(true)
self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
if not self.view then return end
if event == "button" then
if button == "wheelup" then self.scroll_inertia = math.min(self.scroll_inertia, 0) - 5
elseif button == "wheeldown" then self.scroll_inertia = math.max(self.scroll_inertia, 0) + 5
elseif button == "left" then self.view:injectMouseButton(true, 1)
-- elseif button == "middle" then self.view:injectMouseButton(true, 2)
-- elseif button == "right" then self.view:injectMouseButton(true, 3)
end
elseif event == "button-down" then
if button == "wheelup" then self.scroll_inertia = math.min(self.scroll_inertia, 0) - 5
elseif button == "wheeldown" then self.scroll_inertia = math.max(self.scroll_inertia, 0) + 5
elseif button == "left" then self.view:injectMouseButton(false, 1)
-- elseif button == "middle" then self.view:injectMouseButton(false, 2)
-- elseif button == "right" then self.view:injectMouseButton(false, 3)
end
else
self.view:injectMouseMove(bx, by)
end
end)
if core.webview.kind == "awesomium" then
function self.key.receiveKey(_, sym, ctrl, shift, alt, meta, unicode, isup, key, ismouse, keysym)
if not self.view then return end
local symb = self.key.sym_to_name[sym]
if not symb then return end
local asymb = self.awesomiumMapKey[symb]
if not asymb then return end
self.view:injectKey(isup, symb, asymb, unicode)
end
elseif core.webview.kind == "cef3" then
function self.key.receiveKey(_, sym, ctrl, shift, alt, meta, unicode, isup, key, ismouse, keysym)
if not self.view then return end
if unicode then
keysym = unicode:sub(1):byte()
self.view:injectKey(true, keysym, 0, unicode)
return
end
self.view:injectKey(isup, keysym, 0, "")
end
end
end
function _M:on_focus(v)
game:onTickEnd(function() self.key:unicodeInput(v) end)
if self.view then self.view:focus(v) end
end
function _M:makeDownloadbox(downid, file)
local Dialog = require "engine.ui.Dialog"
local Waitbar = require "engine.ui.Waitbar"
local Button = require "engine.ui.Button"
local d = Dialog.new(("Download: "):tformat(file), 600, 100)
local b = Button.new{text=_t"Cancel", fct=function() self.view:downloadAction(downid, false) game:unregisterDialog(d) end}
local w = Waitbar.new{size=600, text=file}
d:loadUI{
{left=0, top=0, ui=w},
{right=0, bottom=0, ui=b},
}
d:setupUI(true, true)
function d:updateFill(...) w:updateFill(...) end
return d
end
function _M:on_dialog_cleanup()
if not self.never_clean then
self.downloader = nil
self.view = nil
end
end
function _M:onDownload(handlers)
local Dialog = require "engine.ui.Dialog"
handlers.on_download_request = function(downid, url, file, mime)
if mime == "application/t-engine-addon" and self.allow_downloads.addons and (url:find("^http://te4%.org/") or url:find("^https://te4%.org/")) then
local path = fs.getRealPath("/addons/")
if path then
local name = file
if self._next_download_name and os.time() - self._next_download_name.time <= 3 then name = self._next_download_name.name self._next_download_name = nil end
Dialog:yesnoPopup(_t"Confirm addon install/update", _t("Are you sure you want to install this addon: #LIGHT_GREEN##{bold}#%s#{normal}##LAST# ?"):tformat(name), function(ret)
if ret then
print("Accepting addon download to:", path..file)
self.download_dialog = self:makeDownloadbox(downid, file)
self.download_dialog.install_kind = "Addon"
game:registerDialog(self.download_dialog)
self.view:downloadAction(downid, path..file)
else
self.view:downloadAction(downid, false)
end
end)
return
end
elseif mime == "application/t-engine-module" and self.allow_downloads.modules and (url:find("^http://te4%.org/") or url:find("^https://te4%.org/")) then
local path = fs.getRealPath("/modules/")
if path then
local name = file
if self._next_download_name and os.time() - self._next_download_name.time <= 3 then name = self._next_download_name.name self._next_download_name = nil end
Dialog:yesnoPopup(_t"Confirm module install/update", ("Are you sure you want to install this module: #LIGHT_GREEN##{bold}#%s#{normal}##LAST#?"):tformat(name), function(ret)
if ret then
print("Accepting module download to:", path..file)
self.download_dialog = self:makeDownloadbox(downid, file)
self.download_dialog.install_kind = "Game Module"
game:registerDialog(self.download_dialog)
self.view:downloadAction(downid, path..file)
else
self.view:downloadAction(downid, false)
end
end)
return
end
end
self.view:downloadAction(downid, false)
end
handlers.on_download_update = function(downid, cur_size, total_size, percent, speed)
if not self.download_dialog then return end
self.download_dialog:updateFill(cur_size, total_size, ("%d%% - %d KB/s"):format(cur_size * 100 / total_size, speed / 1024))
end
handlers.on_download_finish = function(downid)
if not self.download_dialog then return end
game:unregisterDialog(self.download_dialog)
if self.download_dialog.install_kind == "Addon" then
Dialog:simplePopup(_t"Addon installed!", _t"Addon installation successful. New addons are only active for new characters.")
elseif self.download_dialog.install_kind == "Game Module" then
Dialog:simplePopup(_t"Game installed!", _t"Game installation successful. Have fun!")
end
self.download_dialog = nil
end
end
function _M:display(x, y, nb_keyframes, screen_x, screen_y, offset_x, offset_y, local_x, local_y)
if self.scroll_inertia > 0 then self.scroll_inertia = math.max(self.scroll_inertia - 1, 0)
elseif self.scroll_inertia < 0 then self.scroll_inertia = math.min(self.scroll_inertia + 1, 0)
end
if self.frame then
self:drawFrame(self.frame, x - 4, y - 4, 0, 0, 0, 0.3, self.w, self.h) -- shadow
self:drawFrame(self.frame, x - 4, y - 4, 1, 1, 1, 0.75) -- unlocked frame
end
if self.view then
if self.scroll_inertia ~= 0 then self.view:injectMouseWheel(0, self.scroll_inertia) end
self.view:toScreen(x, y)
end
if self.loading < 1 and not self.hide_loading then
self.loading_rotation = self.loading_rotation + nb_keyframes * 8
core.display.glMatrix(true)
core.display.glTranslate(x + self.loading_icon.w / 2, y + self.loading_icon.h / 2, 0)
core.display.glRotate(self.loading_rotation, 0, 0, 1)
self.loading_icon.t:toScreenFull(-self.loading_icon.w / 2, -self.loading_icon.h / 2, self.loading_icon.w, self.loading_icon.h, self.loading_icon.tw, self.loading_icon.th)
core.display.glMatrix(false)
end
end
_M.awesomiumMapKey = {
-- _BACK (08) BACKSPACE key
_BACKSPACE = 0x08,
-- _TAB (09) TAB key
_TAB = 0x09,
-- _CLEAR (0C) CLEAR key
_CLEAR = 0x0C,
-- _RETURN (0D)
_RETURN = 0x0D,
-- _SHIFT (10) SHIFT key
_SHIFT = 0x10,
-- _CONTROL (11) CTRL key
_CONTROL = 0x11,
-- _MENU (12) ALT key
_MENU = 0x12,
-- _PAUSE (13) PAUSE key
_PAUSE = 0x13,
-- _CAPITAL (14) CAPS LOCK key
_CAPITAL = 0x14,
-- _KANA (15) Input Method Editor (IME) Kana mode
_KANA = 0x15,
-- _HANGUEL (15) IME Hanguel mode (maintained for compatibility; use _HANGUL)
-- _HANGUL (15) IME Hangul mode
_HANGUL = 0x15,
-- _JUNJA (17) IME Junja mode
_JUNJA = 0x17,
-- _FINAL (18) IME final mode
_FINAL = 0x18,
-- _HANJA (19) IME Hanja mode
_HANJA = 0x19,
-- _KANJI (19) IME Kanji mode
_KANJI = 0x19,
-- _ESCAPE (1B) ESC key
_ESCAPE = 0x1B,
-- _CONVERT (1C) IME convert
_CONVERT = 0x1C,
-- _NONCONVERT (1D) IME nonconvert
_NONCONVERT = 0x1D,
-- _ACCEPT (1E) IME accept
_ACCEPT = 0x1E,
-- _MODECHANGE (1F) IME mode change request
_MODECHANGE = 0x1F,
-- _SPACE (20) SPACEBAR
_SPACE = 0x20,
-- _PRIOR (21) PAGE UP key
_PRIOR = 0x21,
-- _NEXT (22) PAGE DOWN key
_NEXT = 0x22,
-- _END (23) END key
_END = 0x23,
-- _HOME (24) HOME key
_HOME = 0x24,
-- _LEFT (25) LEFT ARROW key
_LEFT = 0x25,
-- _UP (26) UP ARROW key
_UP = 0x26,
-- _RIGHT (27) RIGHT ARROW key
_RIGHT = 0x27,
-- _DOWN (28) DOWN ARROW key
_DOWN = 0x28,
-- _SELECT (29) SELECT key
_SELECT = 0x29,
-- _PRINT (2A) PRINT key
_PRINT = 0x2A,
-- _EXECUTE (2B) EXECUTE key
_EXECUTE = 0x2B,
-- _SNAPSHOT (2C) PRINT SCREEN key
_SNAPSHOT = 0x2C,
-- _INSERT (2D) INS key
_INSERT = 0x2D,
-- _DELETE (2E) DEL key
_DELETE = 0x2E,
-- _HELP (2F) HELP key
_HELP = 0x2F,
-- (30) 0 key
_0 = 0x30,
-- (31) 1 key
_1 = 0x31,
-- (32) 2 key
_2 = 0x32,
-- (33) 3 key
_3 = 0x33,
-- (34) 4 key
_4 = 0x34,
-- (35) 5 key;
_5 = 0x35,
-- (36) 6 key
_6 = 0x36,
-- (37) 7 key
_7 = 0x37,
-- (38) 8 key
_8 = 0x38,
-- (39) 9 key
_9 = 0x39,
-- (41) A key
_a = 0x41,
-- (42) b key
_b = 0x42,
-- (43) c key
_c = 0x43,
-- (44) d key
_d = 0x44,
-- (45) e key
_e = 0x45,
-- (46) f key
_f = 0x46,
-- (47) g key
_g = 0x47,
-- (48) h key
_h = 0x48,
-- (49) i key
_i = 0x49,
-- (4a) j key
_j = 0x4a,
-- (4b) k key
_k = 0x4b,
-- (4c) l key
_l = 0x4c,
-- (4d) m key
_m = 0x4d,
-- (4e) n key
_n = 0x4e,
-- (4f) o key
_o = 0x4f,
-- (50) p key
_p = 0x50,
-- (51) q key
_q = 0x51,
-- (52) r key
_r = 0x52,
-- (53) s key
_s = 0x53,
-- (54) t key
_t = 0x54,
-- (55) u key
_u = 0x55,
-- (56) v key
_v = 0x56,
-- (57) w key
_w = 0x57,
-- (58) x key
_x = 0x58,
-- (59) y key
_y = 0x59,
-- (5a) z key
_z = 0x5a,
-- _LWIN (5B) Left Windows key (Microsoft Natural keyboard)
_LWIN = 0x5B,
-- _RWIN (5C) Right Windows key (Natural keyboard)
_RWIN = 0x5C,
-- _APPS (5D) Applications key (Natural keyboard)
_APPS = 0x5D,
-- _SLEEP (5F) Computer Sleep key
_SLEEP = 0x5F,
-- _NUMPAD0 (60) Numeric keypad 0 key
_NUMPAD0 = 0x60,
-- _NUMPAD1 (61) Numeric keypad 1 key
_NUMPAD1 = 0x61,
-- _NUMPAD2 (62) Numeric keypad 2 key
_NUMPAD2 = 0x62,
-- _NUMPAD3 (63) Numeric keypad 3 key
_NUMPAD3 = 0x63,
-- _NUMPAD4 (64) Numeric keypad 4 key
_NUMPAD4 = 0x64,
-- _NUMPAD5 (65) Numeric keypad 5 key
_NUMPAD5 = 0x65,
-- _NUMPAD6 (66) Numeric keypad 6 key
_NUMPAD6 = 0x66,
-- _NUMPAD7 (67) Numeric keypad 7 key
_NUMPAD7 = 0x67,
-- _NUMPAD8 (68) Numeric keypad 8 key
_NUMPAD8 = 0x68,
-- _NUMPAD9 (69) Numeric keypad 9 key
_NUMPAD9 = 0x69,
-- _MULTIPLY (6A) Multiply key
_MULTIPLY = 0x6A,
-- _ADD (6B) Add key
_ADD = 0x6B,
-- _SEPARATOR (6C) Separator key
_SEPARATOR = 0x6C,
-- _SUBTRACT (6D) Subtract key
_SUBTRACT = 0x6D,
-- _DECIMAL (6E) Decimal key
_DECIMAL = 0x6E,
-- _DIVIDE (6F) Divide key
_DIVIDE = 0x6F,
-- _F1 (70) F1 key
_F1 = 0x70,
-- _F2 (71) F2 key
_F2 = 0x71,
-- _F3 (72) F3 key
_F3 = 0x72,
-- _F4 (73) F4 key
_F4 = 0x73,
-- _F5 (74) F5 key
_F5 = 0x74,
-- _F6 (75) F6 key
_F6 = 0x75,
-- _F7 (76) F7 key
_F7 = 0x76,
-- _F8 (77) F8 key
_F8 = 0x77,
-- _F9 (78) F9 key
_F9 = 0x78,
-- _F10 (79) F10 key
_F10 = 0x79,
-- _F11 (7A) F11 key
_F11 = 0x7A,
-- _F12 (7B) F12 key
_F12 = 0x7B,
-- _F13 (7C) F13 key
_F13 = 0x7C,
-- _F14 (7D) F14 key
_F14 = 0x7D,
-- _F15 (7E) F15 key
_F15 = 0x7E,
-- _F16 (7F) F16 key
_F16 = 0x7F,
-- _F17 (80H) F17 key
_F17 = 0x80,
-- _F18 (81H) F18 key
_F18 = 0x81,
-- _F19 (82H) F19 key
_F19 = 0x82,
-- _F20 (83H) F20 key
_F20 = 0x83,
-- _F21 (84H) F21 key
_F21 = 0x84,
-- _F22 (85H) F22 key
_F22 = 0x85,
-- _F23 (86H) F23 key
_F23 = 0x86,
-- _F24 (87H) F24 key
_F24 = 0x87,
-- _NUMLOCK (90) NUM LOCK key
_NUMLOCK = 0x90,
-- _SCROLL (91) SCROLL LOCK key
_SCROLL = 0x91,
-- _LSHIFT (A0) Left SHIFT key
_LSHIFT = 0xA0,
-- _RSHIFT (A1) Right SHIFT key
_RSHIFT = 0xA1,
-- _LCONTROL (A2) Left CONTROL key
_LCONTROL = 0xA2,
-- _RCONTROL (A3) Right CONTROL key
_RCONTROL = 0xA3,
-- _LMENU (A4) Left MENU key
_LMENU = 0xA4,
-- _RMENU (A5) Right MENU key
_RMENU = 0xA5,
-- _BROWSER_BACK (A6) Windows 2000/XP: Browser Back key
_BROWSER_BACK = 0xA6,
-- _BROWSER_FORWARD (A7) Windows 2000/XP: Browser Forward key
_BROWSER_FORWARD = 0xA7,
-- _BROWSER_REFRESH (A8) Windows 2000/XP: Browser Refresh key
_BROWSER_REFRESH = 0xA8,
-- _BROWSER_STOP (A9) Windows 2000/XP: Browser Stop key
_BROWSER_STOP = 0xA9,
-- _BROWSER_SEARCH (AA) Windows 2000/XP: Browser Search key
_BROWSER_SEARCH = 0xAA,
-- _BROWSER_FAVORITES (AB) Windows 2000/XP: Browser Favorites key
_BROWSER_FAVORITES = 0xAB,
-- _BROWSER_HOME (AC) Windows 2000/XP: Browser Start and Home key
_BROWSER_HOME = 0xAC,
-- _VOLUME_MUTE (AD) Windows 2000/XP: Volume Mute key
_VOLUME_MUTE = 0xAD,
-- _VOLUME_DOWN (AE) Windows 2000/XP: Volume Down key
_VOLUME_DOWN = 0xAE,
-- _VOLUME_UP (AF) Windows 2000/XP: Volume Up key
_VOLUME_UP = 0xAF,
-- _MEDIA_NEXT_TRACK (B0) Windows 2000/XP: Next Track key
_MEDIA_NEXT_TRACK = 0xB0,
-- _MEDIA_PREV_TRACK (B1) Windows 2000/XP: Previous Track key
_MEDIA_PREV_TRACK = 0xB1,
-- _MEDIA_STOP (B2) Windows 2000/XP: Stop Media key
_MEDIA_STOP = 0xB2,
-- _MEDIA_PLAY_PAUSE (B3) Windows 2000/XP: Play/Pause Media key
_MEDIA_PLAY_PAUSE = 0xB3,
-- _LAUNCH_MAIL (B4) Windows 2000/XP: Start Mail key
_MEDIA_LAUNCH_MAIL = 0xB4,
-- _LAUNCH_MEDIA_SELECT (B5) Windows 2000/XP: Select Media key
_MEDIA_LAUNCH_MEDIA_SELECT = 0xB5,
-- _LAUNCH_APP1 (B6) Windows 2000/XP: Start Application 1 key
_MEDIA_LAUNCH_APP1 = 0xB6,
-- _LAUNCH_APP2 (B7) Windows 2000/XP: Start Application 2 key
_MEDIA_LAUNCH_APP2 = 0xB7,
-- _OEM_1 (BA) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ';:' key
_OEM_1 = 0xBA,
-- _OEM_PLUS (BB) Windows 2000/XP: For any country/region, the '+' key
_OEM_PLUS = 0xBB,
-- _OEM_COMMA (BC) Windows 2000/XP: For any country/region, the ',' key
_OEM_COMMA = 0xBC,
-- _OEM_MINUS (BD) Windows 2000/XP: For any country/region, the '-' key
_OEM_MINUS = 0xBD,
-- _OEM_PERIOD (BE) Windows 2000/XP: For any country/region, the '.' key
_OEM_PERIOD = 0xBE,
-- _OEM_2 (BF) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '/?' key
_OEM_2 = 0xBF,
-- _OEM_3 (C0) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '`~' key
_OEM_3 = 0xC0,
-- _OEM_4 (DB) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '[{' key
_OEM_4 = 0xDB,
-- _OEM_5 (DC) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the '\|' key
_OEM_5 = 0xDC,
-- _OEM_6 (DD) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the ']}' key
_OEM_6 = 0xDD,
-- _OEM_7 (DE) Used for miscellaneous characters; it can vary by keyboard. Windows 2000/XP: For the US standard keyboard, the 'single-quote/double-quote' key
_OEM_7 = 0xDE,
-- _OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
_OEM_8 = 0xDF,
-- _OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
_OEM_102 = 0xE2,
-- _PROCESSKEY (E5) Windows 95/98/Me, Windows NT 4.0, Windows 2000/XP: IME PROCESS key
_PROCESSKEY = 0xE5,
-- _PACKET (E7) Windows 2000/XP: Used to pass Unicode characters as if they were keystrokes. The _PACKET key is the low word of a 32-bit Virtual Key value used for non-keyboard input methods. For more information, see Remark in KEYBDINPUT,SendInput, WM_KEYDOWN, and WM_KEYUP
_PACKET = 0xE7,
-- _ATTN (F6) Attn key
_ATTN = 0xF6,
-- _CRSEL (F7) CrSel key
_CRSEL = 0xF7,
-- _EXSEL (F8) ExSel key
_EXSEL = 0xF8,
-- _EREOF (F9) Erase EOF key
_EREOF = 0xF9,
-- _PLAY (FA) Play key
_PLAY = 0xFA,
-- _ZOOM (FB) Zoom key
_ZOOM = 0xFB,
-- _NONAME (FC) Reserved for future use
_NONAME = 0xFC,
-- _PA1 (FD) PA1 key
_PA1 = 0xFD,
-- _OEM_CLEAR (FE) Clear key
_OEM_CLEAR = 0xFE,
_UNKNOWN = 0,
}
\ No newline at end of file
-- TE4 - T-Engine 4
-- Copyright (C) 2009 - 2019 Nicolas Casalini
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
--
-- Nicolas Casalini "DarkGod"
-- darkgod@te4.org
local class = require "engine.class"
local Base = require "engine.ui.Base"
--- Helper for "title" parameter for UI elements
-- @classmod engine.ui.WithTitle
module(..., package.seeall, class.inherit(Base))
function _M:init(t)
self.title = t.title
self.title_w = t.title_w
self.size_title = t.size_title or t.title
Base.init(self, t)
end
function _M:generateTitle()
if not self.size_title and not self.title_w then
self.title_w = 0
self.title_h = 0
return
end
self.title_w = self.title_w or self.font:size(self.size_title)
self.title_h = self.font:height()
if self.title then
self.title_tex = self:drawFontLine(self.font, self.title, self.title_w)
end
end
function _M:displayTitle(x, y, nb_keyframes)
if self.title_tex then
local title_x = x + (self.title_x or 0)
local title_y = y + (self.title_y or (self.h - self.title_h) / 2)
if self.text_shadow then
self:textureToScreen(self.title_tex, title_x + 1, title_y + 1, 0, 0, 0, self.text_shadow)
end
self:textureToScreen(self.title_tex, title_x, title_y)
end
return x + self.title_w, y
end