lua console and some changes
This commit is contained in:
		
							parent
							
								
									033f14780d
								
							
						
					
					
						commit
						38529ea837
					
				| 
						 | 
				
			
			@ -84,11 +84,11 @@ SET(SOURCES
 | 
			
		|||
    src/framework/net/rsa.cpp
 | 
			
		||||
 | 
			
		||||
    # framework util
 | 
			
		||||
    src/framework/util/logger.cpp
 | 
			
		||||
    src/framework/util/color.cpp
 | 
			
		||||
    src/framework/util/translator.cpp
 | 
			
		||||
 | 
			
		||||
    # framework core
 | 
			
		||||
    src/framework/core/logger.cpp
 | 
			
		||||
    src/framework/core/configs.cpp
 | 
			
		||||
    src/framework/core/resourcemanager.cpp
 | 
			
		||||
    src/framework/core/eventdispatcher.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,74 @@
 | 
			
		|||
Console = { }
 | 
			
		||||
local console
 | 
			
		||||
local logLocked = false
 | 
			
		||||
 | 
			
		||||
function Console.onLog(level, message, time)
 | 
			
		||||
  -- avoid logging while reporting logs (would cause a infinite loop)
 | 
			
		||||
  if not logLocked then
 | 
			
		||||
    logLocked = true
 | 
			
		||||
 | 
			
		||||
    local color
 | 
			
		||||
    if level == LogDebug then
 | 
			
		||||
      color = '#5555ff'
 | 
			
		||||
    elseif level == LogInfo then
 | 
			
		||||
      color = '#55ff55'
 | 
			
		||||
    elseif level == LogWarning then
 | 
			
		||||
      color = '#ffff00'
 | 
			
		||||
    else
 | 
			
		||||
      color = '#ff0000'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Console.addLine(message, color)
 | 
			
		||||
 | 
			
		||||
    logLocked = false
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.addLine(text, color)
 | 
			
		||||
  -- create new label
 | 
			
		||||
  local label = UILabel.create()
 | 
			
		||||
  label:setStyle('ConsoleLabel')
 | 
			
		||||
  label:setText(text)
 | 
			
		||||
  label:setForegroundColor(color)
 | 
			
		||||
 | 
			
		||||
  console:insertChild(label, -1)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.create()
 | 
			
		||||
  console = loadUI("/console/console.otui")
 | 
			
		||||
  rootWidget:addChild(console)
 | 
			
		||||
  console:hide()
 | 
			
		||||
 | 
			
		||||
  Logger.setOnLog(Console.onLog)
 | 
			
		||||
  Logger.fireOldMessages()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.destroy()
 | 
			
		||||
  console:destroy()
 | 
			
		||||
  console = nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.show()
 | 
			
		||||
  console.parent:lockChild(console)
 | 
			
		||||
  console.visible = true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.hide()
 | 
			
		||||
  console.parent:unlockChild(console)
 | 
			
		||||
  console.visible = false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Console.executeCommand(command)
 | 
			
		||||
  Console.addLine(">> " .. command, "#ffffff")
 | 
			
		||||
  local func, err = loadstring("return (" .. command .. ")", "@")
 | 
			
		||||
  if func then
 | 
			
		||||
    local ok, ret = pcall(func)
 | 
			
		||||
    if ok then
 | 
			
		||||
      Logger.log(LogDebug, "=> " .. tostring(ret))
 | 
			
		||||
    else
 | 
			
		||||
      Logger.log(LogError, 'command failed: ' .. ret)
 | 
			
		||||
    end
 | 
			
		||||
  else
 | 
			
		||||
    Logger.log(LogError, 'incorrect lua syntax: ' .. err:sub(5))
 | 
			
		||||
  end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
Module
 | 
			
		||||
  name: console
 | 
			
		||||
  description: Console for executing lua functions
 | 
			
		||||
  author: OTClient team
 | 
			
		||||
  website: https://github.com/edubart/otclient
 | 
			
		||||
  version: 0.2
 | 
			
		||||
  autoLoad: true
 | 
			
		||||
  dependencies:
 | 
			
		||||
    - core
 | 
			
		||||
 | 
			
		||||
  onLoad: |
 | 
			
		||||
    require 'console'
 | 
			
		||||
    Console.create()
 | 
			
		||||
    return true
 | 
			
		||||
 | 
			
		||||
  onUnload: |
 | 
			
		||||
    Console.destroy()
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
ConsoleLabel < UILabel
 | 
			
		||||
  font: terminus-14px-bold
 | 
			
		||||
  height: 16
 | 
			
		||||
  anchors.bottom: next.top
 | 
			
		||||
  anchors.left: parent.left
 | 
			
		||||
  anchors.right: parent.right
 | 
			
		||||
  margin.left: 2
 | 
			
		||||
 | 
			
		||||
RectPanel
 | 
			
		||||
  id: consolePanel
 | 
			
		||||
  background-color: #000000
 | 
			
		||||
  opacity: 216
 | 
			
		||||
  anchors.fill: parent
 | 
			
		||||
 | 
			
		||||
  UILabel
 | 
			
		||||
    size: 18 20
 | 
			
		||||
    anchors.bottom: parent.bottom
 | 
			
		||||
    anchors.left: parent.left
 | 
			
		||||
    margin.left: 2
 | 
			
		||||
    font: terminus-14px-bold
 | 
			
		||||
    text: >>
 | 
			
		||||
 | 
			
		||||
  UILineEdit
 | 
			
		||||
    id: commandBox
 | 
			
		||||
    height: 20
 | 
			
		||||
    anchors.bottom: parent.bottom
 | 
			
		||||
    anchors.left: prev.right
 | 
			
		||||
    anchors.right: parent.right
 | 
			
		||||
    margin.left: 2
 | 
			
		||||
    font: terminus-14px-bold
 | 
			
		||||
    onAction: |
 | 
			
		||||
      function(self)
 | 
			
		||||
        Console.executeCommand(self:getText())
 | 
			
		||||
        self:clearText()
 | 
			
		||||
      end
 | 
			
		||||
| 
						 | 
				
			
			@ -6,3 +6,11 @@ AnchorLeft = 3
 | 
			
		|||
AnchorRight = 4
 | 
			
		||||
AnchorVerticalCenter = 5
 | 
			
		||||
AnchorHorizontalCenter = 6
 | 
			
		||||
 | 
			
		||||
LogDebug = 0
 | 
			
		||||
LogInfo = 1
 | 
			
		||||
LogWarning = 2
 | 
			
		||||
LogError = 3
 | 
			
		||||
LogFatal = 4
 | 
			
		||||
 | 
			
		||||
EmptyFunction = function() end
 | 
			
		||||
| 
						 | 
				
			
			@ -11,45 +11,48 @@ function MessageBox.create(title, text, flags)
 | 
			
		|||
 | 
			
		||||
  -- create messagebox window
 | 
			
		||||
  local window = UIWindow.create()
 | 
			
		||||
  window.id = "messageBoxWindow"
 | 
			
		||||
  window.title = title
 | 
			
		||||
  window:setStyle('Window')
 | 
			
		||||
  window:setId("messageBoxWindow")
 | 
			
		||||
  window:setTitle(title)
 | 
			
		||||
  window:centerIn("parent")
 | 
			
		||||
  rootWidget:addChild(window)
 | 
			
		||||
  window:lock()
 | 
			
		||||
  rootWidget:lockChild(window)
 | 
			
		||||
 | 
			
		||||
  -- create messagebox label
 | 
			
		||||
  local label = UILabel.create()
 | 
			
		||||
  label.id = "messageBoxLabel"
 | 
			
		||||
  label.text = text
 | 
			
		||||
  label:addAnchor(AnchorHorizontalCenter, window.id, AnchorHorizontalCenter)
 | 
			
		||||
  label:addAnchor(AnchorTop, window.id, AnchorTop)
 | 
			
		||||
  label:setStyle('Label')
 | 
			
		||||
  label:setId("messageBoxLabel")
 | 
			
		||||
  label:setText(text)
 | 
			
		||||
  label:addAnchor(AnchorHorizontalCenter, window:getId(), AnchorHorizontalCenter)
 | 
			
		||||
  label:addAnchor(AnchorTop, window:getId(), AnchorTop)
 | 
			
		||||
  label:setMargin(27, 0)
 | 
			
		||||
  label:resizeToText()
 | 
			
		||||
  window:addChild(label)
 | 
			
		||||
 | 
			
		||||
  -- set window size based on label size
 | 
			
		||||
  window.width = label.width + 60
 | 
			
		||||
  window.height = label.height + 64
 | 
			
		||||
  window:setWidth(label:getWidth() + 60)
 | 
			
		||||
  window:setHeight(label:getHeight() + 64)
 | 
			
		||||
 | 
			
		||||
  -- setup messagebox first button
 | 
			
		||||
  local button1 = UIButton.create()
 | 
			
		||||
  button1.id = "messageBoxButton1"
 | 
			
		||||
  button1:addAnchor(AnchorBottom, window.id, AnchorBottom)
 | 
			
		||||
  button1:addAnchor(AnchorRight, window.id, AnchorRight)
 | 
			
		||||
  button1:setStyle('Button')
 | 
			
		||||
  button1:setId("messageBoxButton1")
 | 
			
		||||
  button1:addAnchor(AnchorBottom, window:getId(), AnchorBottom)
 | 
			
		||||
  button1:addAnchor(AnchorRight, window:getId(), AnchorRight)
 | 
			
		||||
  button1:setMargin(10)
 | 
			
		||||
  button1.width = 64
 | 
			
		||||
  button1:setWidth(64)
 | 
			
		||||
  window:addChild(button1)
 | 
			
		||||
 | 
			
		||||
  if flags == MessageBoxOk then
 | 
			
		||||
    button1.text = "Ok"
 | 
			
		||||
    box.onOk = createEmptyFunction()
 | 
			
		||||
    button1:setText("Ok")
 | 
			
		||||
    box.onOk = EmptyFunction
 | 
			
		||||
    button1.onClick = function()
 | 
			
		||||
      box.onOk()
 | 
			
		||||
      box:destroy()
 | 
			
		||||
    end
 | 
			
		||||
  elseif flags == MessageBoxCancel then
 | 
			
		||||
    button1.text = "Cancel"
 | 
			
		||||
    box.onCancel = createEmptyFunction()
 | 
			
		||||
    button1:setText("Cancel")
 | 
			
		||||
    box.onCancel = EmptyFunction
 | 
			
		||||
    button1.onClick = function()
 | 
			
		||||
      box.onCancel()
 | 
			
		||||
      box:destroy()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,5 +1,7 @@
 | 
			
		|||
function createEmptyFunction()
 | 
			
		||||
  local emptyFunction = function() end
 | 
			
		||||
  return emptyFunction
 | 
			
		||||
function print(...)
 | 
			
		||||
  local msg = ""
 | 
			
		||||
  for i,v in ipairs(arg) do
 | 
			
		||||
    msg = msg .. tostring(v) .. "\t"
 | 
			
		||||
  end
 | 
			
		||||
  Logger.log(LogInfo, msg)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,19 @@
 | 
			
		|||
function UIWidget:setMargin(...)
 | 
			
		||||
    local params = {...}
 | 
			
		||||
    if #params == 1 then
 | 
			
		||||
        self.marginTop = params[1]
 | 
			
		||||
        self.marginRight = params[1]
 | 
			
		||||
        self.marginBottom = params[1]
 | 
			
		||||
        self.marginLeft = params[1]
 | 
			
		||||
        self:setMarginTop(params[1])
 | 
			
		||||
        self:setMarginRight(params[1])
 | 
			
		||||
        self:setMarginBottom(params[1])
 | 
			
		||||
        self:setMarginLeft(params[1])
 | 
			
		||||
    elseif #params == 2 then
 | 
			
		||||
        self.marginTop = params[1]
 | 
			
		||||
        self.marginRight = params[2]
 | 
			
		||||
        self.marginBottom = params[1]
 | 
			
		||||
        self.marginLeft = params[2]
 | 
			
		||||
        self:setMarginTop(params[1])
 | 
			
		||||
        self:setMarginRight(params[2])
 | 
			
		||||
        self:setMarginBottom(params[1])
 | 
			
		||||
        self:setMarginLeft(params[2])
 | 
			
		||||
    elseif #params == 4 then
 | 
			
		||||
        self.marginTop = params[1]
 | 
			
		||||
        self.marginRight = params[2]
 | 
			
		||||
        self.marginBottom = params[3]
 | 
			
		||||
        self.marginLeft = params[4]
 | 
			
		||||
        self:setMarginTop(params[1])
 | 
			
		||||
        self:setMarginRight(params[2])
 | 
			
		||||
        self:setMarginBottom(params[3])
 | 
			
		||||
        self:setMarginLeft(params[4])
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -11,6 +11,7 @@ Module
 | 
			
		|||
    importFont('helvetica-12px-bold')
 | 
			
		||||
    importFont('helvetica-12px')
 | 
			
		||||
    importFont('helvetica-14px-bold')
 | 
			
		||||
    importFont('terminus-14px-bold')
 | 
			
		||||
 | 
			
		||||
    setDefaultFont('helvetica-12px')
 | 
			
		||||
    return true
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
Font
 | 
			
		||||
  name: terminus-14px-bold
 | 
			
		||||
  height: 16
 | 
			
		||||
  spacing: 0 0
 | 
			
		||||
  top margin: 2
 | 
			
		||||
  texture: terminus-14px-bold.png
 | 
			
		||||
  glyph size: 16 16
 | 
			
		||||
  fixed glyph width: 8
 | 
			
		||||
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 3.6 KiB  | 
| 
						 | 
				
			
			@ -1,6 +1,6 @@
 | 
			
		|||
Button < UIButton
 | 
			
		||||
  font: helvetica-11px-bold
 | 
			
		||||
  font-color: #f0ad4dff
 | 
			
		||||
  color: #f0ad4dff
 | 
			
		||||
  size: 106 24
 | 
			
		||||
  border-image:
 | 
			
		||||
    source: /core_ui/images/button.png
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 191 B  | 
| 
						 | 
				
			
			@ -1,5 +1,8 @@
 | 
			
		|||
Label < UILabel
 | 
			
		||||
  font: helvetica-12px
 | 
			
		||||
  color: #ffffff
 | 
			
		||||
 | 
			
		||||
LargerLabel < Label
 | 
			
		||||
  font: helvetica-12px-bold
 | 
			
		||||
  color: #ffffff
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
LineEdit < UILineEdit
 | 
			
		||||
  font: helvetica-12px
 | 
			
		||||
  size: 86 20
 | 
			
		||||
  text-margin: 3
 | 
			
		||||
  border-image:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,4 +12,4 @@ RoundedPanel < Panel
 | 
			
		|||
    border: 4
 | 
			
		||||
 | 
			
		||||
RectPanel < UIWidget
 | 
			
		||||
  image: /core_ui/images/emptyrect.png
 | 
			
		||||
  image: /core_ui/images/empty_rect.png
 | 
			
		||||
| 
						 | 
				
			
			@ -1,4 +1,5 @@
 | 
			
		|||
Window < UIWindow
 | 
			
		||||
  font: helvetica-12px-bold
 | 
			
		||||
  size: 200 200
 | 
			
		||||
  head:
 | 
			
		||||
    height: 20
 | 
			
		||||
| 
						 | 
				
			
			@ -18,4 +19,3 @@ Window < UIWindow
 | 
			
		|||
 | 
			
		||||
MainWindow < Window
 | 
			
		||||
  anchors.centerIn: parent
 | 
			
		||||
  onLoad: function(self) self:lock() end
 | 
			
		||||
| 
						 | 
				
			
			@ -3,7 +3,7 @@ GFX = { }
 | 
			
		|||
function GFX.fadeIn(widget, time, elapsed)
 | 
			
		||||
    if not elapsed then elapsed = 0 end
 | 
			
		||||
    if not time then time = 250 end
 | 
			
		||||
    widget.opacity = math.min((255*elapsed)/time, 255)
 | 
			
		||||
    widget:setOpacity(math.min((255*elapsed)/time, 255))
 | 
			
		||||
    if elapsed < time then
 | 
			
		||||
        scheduleEvent(function()
 | 
			
		||||
                        GFX.fadeIn(widget, time, elapsed + 30)
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ end
 | 
			
		|||
function GFX.fadeOut(widget, time, elapsed)
 | 
			
		||||
    if not elapsed then elapsed = 0 end
 | 
			
		||||
    if not time then time = 250 end
 | 
			
		||||
    widget.opacity = (255*(time - elapsed))/time
 | 
			
		||||
    widget:setOpacity((255*(time - elapsed))/time)
 | 
			
		||||
    if elapsed < time then
 | 
			
		||||
        scheduleEvent(function()
 | 
			
		||||
                        GFX.fadeOut(widget, time, elapsed + 30)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,8 +31,8 @@ function EnterGame_connectToLoginServer()
 | 
			
		|||
  end
 | 
			
		||||
 | 
			
		||||
  local enterGameWindow = rootWidget:getChild("enterGameWindow")
 | 
			
		||||
  local account = enterGameWindow:getChild("accountNameLineEdit").text
 | 
			
		||||
  local password = enterGameWindow:getChild("accountPasswordLineEdit").text
 | 
			
		||||
  local account = enterGameWindow:getChild("accountNameLineEdit"):getText()
 | 
			
		||||
  local password = enterGameWindow:getChild("accountPasswordLineEdit"):getText()
 | 
			
		||||
  protocolLogin:login(account, password)
 | 
			
		||||
 | 
			
		||||
  enterGameWindow:destroy()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -50,4 +50,4 @@ MainWindow
 | 
			
		|||
    anchors.bottom: parent.bottom
 | 
			
		||||
    margin.bottom: 16
 | 
			
		||||
    margin.right: 16
 | 
			
		||||
    onClick: function(self) GFX.fadeOut(self.parent) end
 | 
			
		||||
    onClick: function(self) GFX.fadeOut(self:getParent()) end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,4 +58,4 @@ MainWindow
 | 
			
		|||
    anchors.top: parent.top
 | 
			
		||||
    margin.top: 191
 | 
			
		||||
    margin.left: 188
 | 
			
		||||
    onClick: function(self) self.parent:destroy() end
 | 
			
		||||
    onClick: function(self) self:getParent():destroy() end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,4 +113,4 @@ MainWindow
 | 
			
		|||
    anchors.bottom: parent.bottom
 | 
			
		||||
    margin.right: 10
 | 
			
		||||
    margin.bottom: 13
 | 
			
		||||
    onClick: function(self) self.parent:destroy() end
 | 
			
		||||
    onClick: function(self) self:getParent():destroy() end
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,14 @@
 | 
			
		|||
 | 
			
		||||
//namespace fw {
 | 
			
		||||
 | 
			
		||||
enum LogLevel {
 | 
			
		||||
    LogDebug = 0,
 | 
			
		||||
    LogInfo,
 | 
			
		||||
    LogWarning,
 | 
			
		||||
    LogError,
 | 
			
		||||
    LogFatal
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum AlignmentFlag {
 | 
			
		||||
    AlignLeft = 1,
 | 
			
		||||
    AlignRight = 2,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,17 +5,20 @@
 | 
			
		|||
 | 
			
		||||
Configs g_configs;
 | 
			
		||||
 | 
			
		||||
bool Configs::load(const std::string& fileName)
 | 
			
		||||
bool Configs::load(const std::string& file)
 | 
			
		||||
{
 | 
			
		||||
    m_fileName = fileName;
 | 
			
		||||
    m_fileName = file;
 | 
			
		||||
 | 
			
		||||
    if(!g_resources.fileExists(file))
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        OTMLDocumentPtr doc = OTMLDocument::parse(fileName);
 | 
			
		||||
        OTMLDocumentPtr doc = OTMLDocument::parse(file);
 | 
			
		||||
        for(const OTMLNodePtr& child : doc->children())
 | 
			
		||||
            m_confsMap[child->tag()] = child->value();
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: could not load configurations: ", e.what());
 | 
			
		||||
        logError("could not load configurations: ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@
 | 
			
		|||
class Configs
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    bool load(const std::string& fileName);
 | 
			
		||||
    bool load(const std::string& file);
 | 
			
		||||
    bool save();
 | 
			
		||||
 | 
			
		||||
    void set(const std::string& key, const std::string& value) { m_confsMap[key] = value; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,52 @@
 | 
			
		|||
#include "logger.h"
 | 
			
		||||
#include "eventdispatcher.h"
 | 
			
		||||
 | 
			
		||||
Logger g_logger;
 | 
			
		||||
 | 
			
		||||
Logger::Logger() : m_terminated(false)
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Logger::log(LogLevel level, std::string message)
 | 
			
		||||
{
 | 
			
		||||
    const static std::string logPrefixes[] = { "", "", "WARNING: ", "ERROR: ", "FATAL ERROR: " };
 | 
			
		||||
 | 
			
		||||
    if(!m_terminated) {
 | 
			
		||||
        message.insert(0, logPrefixes[level]);
 | 
			
		||||
        std::cout << message << std::endl;
 | 
			
		||||
 | 
			
		||||
        std::size_t now = std::time(NULL);
 | 
			
		||||
        m_logMessages.push_back(LogMessage(level, message, now));
 | 
			
		||||
 | 
			
		||||
        if(m_onLog)
 | 
			
		||||
            g_dispatcher.addEvent(std::bind(m_onLog, level, message, now));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(level == LogFatal) {
 | 
			
		||||
        m_terminated = true;
 | 
			
		||||
        exit(-1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Logger::logFunc(LogLevel level, const std::string& message, std::string prettyFunction)
 | 
			
		||||
{
 | 
			
		||||
    std::stringstream ss;
 | 
			
		||||
    prettyFunction = prettyFunction.substr(0, prettyFunction.find_first_of('('));
 | 
			
		||||
    if(prettyFunction.find_last_of(' ') != std::string::npos)
 | 
			
		||||
        prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
 | 
			
		||||
 | 
			
		||||
    if(!prettyFunction.empty())
 | 
			
		||||
        ss << "[" << prettyFunction << "] ";
 | 
			
		||||
 | 
			
		||||
    ss << message;
 | 
			
		||||
    log(level, ss.str());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Logger::fireOldMessages()
 | 
			
		||||
{
 | 
			
		||||
    if(m_onLog) {
 | 
			
		||||
        for(const LogMessage& logMessage : m_logMessages)
 | 
			
		||||
            g_dispatcher.addEvent(std::bind(m_onLog, logMessage.level, logMessage.message, logMessage.when));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,49 @@
 | 
			
		|||
#ifndef LOGGER_H
 | 
			
		||||
#define LOGGER_H
 | 
			
		||||
 | 
			
		||||
#include "../util/tools.h"
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <functional>
 | 
			
		||||
 | 
			
		||||
struct LogMessage {
 | 
			
		||||
  LogMessage(LogLevel level, const std::string& message, std::size_t when) : level(level), message(message), when(when) { }
 | 
			
		||||
  LogLevel level;
 | 
			
		||||
  std::string message;
 | 
			
		||||
  std::size_t when;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Logger
 | 
			
		||||
{
 | 
			
		||||
    typedef std::function<void(LogLevel, std::string, std::size_t)> OnLogCallback;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    Logger();
 | 
			
		||||
 | 
			
		||||
    void log(LogLevel level, std::string message);
 | 
			
		||||
    void logFunc(LogLevel level, const std::string& message, std::string prettyFunction);
 | 
			
		||||
 | 
			
		||||
    void fireOldMessages();
 | 
			
		||||
    void setOnLog(const OnLogCallback& onLog) { m_onLog = onLog; }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::vector<LogMessage> m_logMessages;
 | 
			
		||||
    OnLogCallback m_onLog;
 | 
			
		||||
    bool m_terminated;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern Logger g_logger;
 | 
			
		||||
 | 
			
		||||
// specialized logging
 | 
			
		||||
#define logDebug(...) g_logger.log(LogDebug, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logInfo(...) g_logger.log(LogInfo, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logWarning(...) g_logger.log(LogWarning, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logError(...) g_logger.log(LogError, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logFatal(...) g_logger.log(LogFatal, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
 | 
			
		||||
#define logTrace() g_logger.logFunc(LogDebug, "", __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceDebug(...) g_logger.logFunc(LogDebug, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceInfo(...) g_logger.logFunc(LogInfo, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceWarning(...) g_logger.logFunc(LogWarning, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceError(...) g_logger.logFunc(LogError, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ bool Module::load()
 | 
			
		|||
        logInfo("Loaded module '", m_name, "'");
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: failed to load module '", m_name, "': ", e.what());
 | 
			
		||||
        logError("failed to load module '", m_name, "': ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ bool ModuleManager::discoverModule(const std::string& file)
 | 
			
		|||
        module->discover(moduleNode);
 | 
			
		||||
        m_modules.push_back(module);
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: failed to load module from '", file, "': ", e.what());
 | 
			
		||||
        logError("failed to load module from '", file, "': ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,14 +30,14 @@ void ResourceManager::init(const char* argv0)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    if(!found)
 | 
			
		||||
        logFatal("FATAL ERROR: could not find modules directory");
 | 
			
		||||
        logFatal("could not find modules directory");
 | 
			
		||||
 | 
			
		||||
    // setup write directory
 | 
			
		||||
    std::string dir = g_platform.getAppUserDir();
 | 
			
		||||
    if(g_resources.setWriteDir(dir))
 | 
			
		||||
        g_resources.addToSearchPath(dir);
 | 
			
		||||
    else
 | 
			
		||||
        logError("ERROR: could not setup write directory");
 | 
			
		||||
        logError("could not setup write directory");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void ResourceManager::terminate()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,13 +41,15 @@
 | 
			
		|||
// additional utilities
 | 
			
		||||
#include "util/types.h"
 | 
			
		||||
#include "util/tools.h"
 | 
			
		||||
#include "util/logger.h"
 | 
			
		||||
#include "util/translator.h"
 | 
			
		||||
#include "util/point.h"
 | 
			
		||||
#include "util/color.h"
 | 
			
		||||
#include "util/rect.h"
 | 
			
		||||
#include "util/size.h"
 | 
			
		||||
 | 
			
		||||
// logger
 | 
			
		||||
#include "core/logger.h"
 | 
			
		||||
 | 
			
		||||
// easy typing for _1, _2, ...
 | 
			
		||||
using namespace std::placeholders;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,10 @@ void Font::load(const OTMLNodePtr& fontNode)
 | 
			
		|||
    if(!m_texture)
 | 
			
		||||
        throw std::runtime_error("failed to load texture for font");
 | 
			
		||||
 | 
			
		||||
    // auto calculate widths
 | 
			
		||||
    if(OTMLNodePtr node = fontNode->get("fixed glyph width")) {
 | 
			
		||||
        for(int glyph = m_firstGlyph; glyph < 256; ++glyph)
 | 
			
		||||
            m_glyphsSize[glyph] = Size(node->value<int>(), m_glyphHeight);
 | 
			
		||||
    } else
 | 
			
		||||
        calculateGlyphsWidthsAutomatically(glyphSize);
 | 
			
		||||
 | 
			
		||||
    // read custom widths
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ bool FontManager::importFont(std::string fontFile)
 | 
			
		|||
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: could not load font from '", fontFile, "': ", e.what());
 | 
			
		||||
        logError("could not load font from '", fontFile, "': ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +64,6 @@ FontPtr FontManager::getDefaultFont()
 | 
			
		|||
{
 | 
			
		||||
    // default font should always exists, otherwise the app may crash
 | 
			
		||||
    if(!m_defaultFont)
 | 
			
		||||
        logFatal("FATAL ERROR: no default font to display, cannot continue to run");
 | 
			
		||||
        logFatal("no default font to display, cannot continue to run");
 | 
			
		||||
    return m_defaultFont;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -194,8 +194,7 @@ void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords,
 | 
			
		|||
        stopDrawing();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Graphics::drawFilledRect(const Rect& screenCoords,
 | 
			
		||||
                              const Color& color)
 | 
			
		||||
void Graphics::drawFilledRect(const Rect& screenCoords)
 | 
			
		||||
{
 | 
			
		||||
    assert(!m_drawing);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,8 +207,6 @@ void Graphics::drawFilledRect(const Rect& screenCoords,
 | 
			
		|||
    int top = screenCoords.top();
 | 
			
		||||
    int left = screenCoords.left();
 | 
			
		||||
 | 
			
		||||
    glPushAttrib(GL_CURRENT_BIT);
 | 
			
		||||
    glColor4ubv(color.rgbaPtr());
 | 
			
		||||
    glDisable(GL_TEXTURE_2D);
 | 
			
		||||
    glBegin(GL_QUADS);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,12 +217,10 @@ void Graphics::drawFilledRect(const Rect& screenCoords,
 | 
			
		|||
 | 
			
		||||
    glEnd();
 | 
			
		||||
    glEnable(GL_TEXTURE_2D);
 | 
			
		||||
    glPopAttrib();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Graphics::drawBoundingRect(const Rect& screenCoords,
 | 
			
		||||
                                const Color& color,
 | 
			
		||||
                                int innerLineWidth)
 | 
			
		||||
{
 | 
			
		||||
    assert(!m_drawing);
 | 
			
		||||
| 
						 | 
				
			
			@ -239,8 +234,6 @@ void Graphics::drawBoundingRect(const Rect& screenCoords,
 | 
			
		|||
    int top = screenCoords.top();
 | 
			
		||||
    int left = screenCoords.left();
 | 
			
		||||
 | 
			
		||||
    glPushAttrib(GL_CURRENT_BIT);
 | 
			
		||||
    glColor4ubv(color.rgbaPtr());
 | 
			
		||||
    glDisable(GL_TEXTURE_2D);
 | 
			
		||||
    glBegin(GL_QUADS);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +263,6 @@ void Graphics::drawBoundingRect(const Rect& screenCoords,
 | 
			
		|||
 | 
			
		||||
    glEnd();
 | 
			
		||||
    glEnable(GL_TEXTURE_2D);
 | 
			
		||||
    glPopAttrib();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Graphics::bindColor(const Color& color)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,11 +45,9 @@ public:
 | 
			
		|||
                                  const TexturePtr& texture,
 | 
			
		||||
                                  const Rect& textureCoords);
 | 
			
		||||
 | 
			
		||||
    void drawFilledRect(const Rect& screenCoords,
 | 
			
		||||
                        const Color& color);
 | 
			
		||||
    void drawFilledRect(const Rect& screenCoords);
 | 
			
		||||
 | 
			
		||||
    void drawBoundingRect(const Rect& screenCoords,
 | 
			
		||||
                          const Color& color = Color::green,
 | 
			
		||||
                          int innerLineWidth = 1);
 | 
			
		||||
 | 
			
		||||
    const Size& getScreenSize() const { return m_screenSize; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -35,7 +35,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
 | 
			
		|||
 | 
			
		||||
    // checks texture max size
 | 
			
		||||
    if(width > maxTexSize || height > maxTexSize) {
 | 
			
		||||
        logError("ERROR: loading texture with size ", width, "x", height, " failed, "
 | 
			
		||||
        logError("loading texture with size ", width, "x", height, " failed, "
 | 
			
		||||
                 "the maximum size allowed by the graphics card is ", maxTexSize, "x", maxTexSize, ",",
 | 
			
		||||
                 "to prevent crashes the texture will be displayed as a blank texture");
 | 
			
		||||
        return 0;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ TexturePtr TextureManager::getTexture(const std::string& textureFile)
 | 
			
		|||
            g_resources.loadFile(textureFile, fin);
 | 
			
		||||
            texture = loadPNG(fin);
 | 
			
		||||
        } catch(std::exception& e) {
 | 
			
		||||
            logError("ERROR: unable to load texture '",textureFile,"': ", e.what());
 | 
			
		||||
            logError("unable to load texture '",textureFile,"': ", e.what());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,51 +10,71 @@ void LuaInterface::registerFunctions()
 | 
			
		|||
    // UIWidget
 | 
			
		||||
    g_lua.registerClass<UIWidget>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create);
 | 
			
		||||
 | 
			
		||||
    g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy);
 | 
			
		||||
    g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild);
 | 
			
		||||
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("id", &UIWidget::getId, &UIWidget::setId);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("enabled", &UIWidget::isEnabled, &UIWidget::setEnabled);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("visible", &UIWidget::isVisible, &UIWidget::setVisible);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("width", &UIWidget::getWidth, &UIWidget::setWidth);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("height", &UIWidget::getHeight, &UIWidget::setHeight);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("parent", &UIWidget::getParent, &UIWidget::setParent);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("color", &UIWidget::getColor, &UIWidget::setColor);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("opacity", &UIWidget::getOpacity, &UIWidget::setOpacity);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("marginTop", &UIWidget::getMarginTop, &UIWidget::setMarginTop);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("marginBottom", &UIWidget::getMarginBottom, &UIWidget::setMarginBottom);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("marginLeft", &UIWidget::getMarginLeft, &UIWidget::setMarginLeft);
 | 
			
		||||
    g_lua.bindClassMemberField<UIWidget>("marginRight", &UIWidget::getMarginRight, &UIWidget::setMarginRight);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getId", &UIWidget::getId);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setId", &UIWidget::setId);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setEnabled", &UIWidget::setEnabled);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("isVisible", &UIWidget::isVisible);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setVisible", &UIWidget::setVisible);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getWidth", &UIWidget::getWidth);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setWidth", &UIWidget::setWidth);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getHeight", &UIWidget::getHeight);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setHeight", &UIWidget::setHeight);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getParent", &UIWidget::getParent);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setParent", &UIWidget::setParent);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getBackgroundColor", &UIWidget::getBackgroundColor);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setBackgroundColor", &UIWidget::setBackgroundColor);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getForegroundColor", &UIWidget::getForegroundColor);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setForegroundColor", &UIWidget::setForegroundColor);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getOpacity", &UIWidget::getOpacity);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setOpacity", &UIWidget::setOpacity);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::setStyle);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setMarginTop", &UIWidget::setMarginTop);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getMarginBottom", &UIWidget::getMarginBottom);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setMarginBottom", &UIWidget::setMarginBottom);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getMarginLeft", &UIWidget::getMarginLeft);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setMarginLeft", &UIWidget::setMarginLeft);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getMarginRight", &UIWidget::getMarginRight);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("setMarginRight", &UIWidget::setMarginRight);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("hide", &UIWidget::hide);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("show", &UIWidget::show);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("fill", &UIWidget::fill);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("centerIn", &UIWidget::centerIn);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("addAnchor", &UIWidget::addAnchor);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("getChild", &UIWidget::getChildById);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("insertChild", &UIWidget::insertChild);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("removeChild", &UIWidget::removeChild);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("addChild", &UIWidget::addChild);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("lock", &UIWidget::lock);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("hide", &UIWidget::hide);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("show", &UIWidget::show);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("lockChild", &UIWidget::lockChild);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWidget>("destroy", &UIWidget::destroy);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // UILabel
 | 
			
		||||
    g_lua.registerClass<UILabel, UIWidget>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<UILabel>("create", &UILabel::create);
 | 
			
		||||
    g_lua.bindClassMemberField("text", &UILabel::getText, &UILabel::setText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UILabel>("getText", &UILabel::getText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UILabel>("setText", &UILabel::setText);
 | 
			
		||||
    g_lua.bindClassMemberFunction("resizeToText", &UILabel::resizeToText);
 | 
			
		||||
 | 
			
		||||
    // UIButton
 | 
			
		||||
    g_lua.registerClass<UIButton, UIWidget>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<UIButton>("create", &UIButton::create);
 | 
			
		||||
    g_lua.bindClassMemberField("text", &UIButton::getText, &UIButton::setText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIButton>("getText", &UIButton::getText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIButton>("setText", &UIButton::setText);
 | 
			
		||||
 | 
			
		||||
    // UILineEdit
 | 
			
		||||
    g_lua.registerClass<UILineEdit, UIWidget>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<UILineEdit>("create", &UILineEdit::create);
 | 
			
		||||
    g_lua.bindClassMemberField("text", &UILineEdit::getText, &UILineEdit::setText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UILineEdit>("getText", &UILineEdit::getText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UILineEdit>("setText", &UILineEdit::setText);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UILineEdit>("clearText", &UILineEdit::clearText);
 | 
			
		||||
 | 
			
		||||
    // UIWindow
 | 
			
		||||
    g_lua.registerClass<UIWindow, UIWidget>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<UIWindow>("create", &UIWindow::create);
 | 
			
		||||
    g_lua.bindClassMemberField("title", &UIWindow::getTitle, &UIWindow::setTitle);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWindow>("getTitle", &UIWindow::getTitle);
 | 
			
		||||
    g_lua.bindClassMemberFunction<UIWindow>("setTitle", &UIWindow::setTitle);
 | 
			
		||||
 | 
			
		||||
    // Protocol
 | 
			
		||||
    g_lua.registerClass<Protocol>();
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +84,12 @@ void LuaInterface::registerFunctions()
 | 
			
		|||
    g_lua.bindClassStaticFunction<Configs>("set", std::bind(&Configs::set, &g_configs, _1, _2));
 | 
			
		||||
    g_lua.bindClassStaticFunction<Configs>("get", std::bind(&Configs::get, &g_configs, _1));
 | 
			
		||||
 | 
			
		||||
    // Logger
 | 
			
		||||
    g_lua.registerClass<Logger>();
 | 
			
		||||
    g_lua.bindClassStaticFunction<Logger>("log", std::bind(&Logger::log, &g_logger, _1, _2));
 | 
			
		||||
    g_lua.bindClassStaticFunction<Logger>("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger));
 | 
			
		||||
    g_lua.bindClassStaticFunction<Logger>("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1));
 | 
			
		||||
 | 
			
		||||
    // global functions
 | 
			
		||||
    g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1));
 | 
			
		||||
    g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -422,7 +422,7 @@ int LuaInterface::protectedCall(int numArgs, int requestedResults)
 | 
			
		|||
            throw LuaException("attempt to call a non function value", 0);
 | 
			
		||||
        }
 | 
			
		||||
    } catch(LuaException &e) {
 | 
			
		||||
        logError(e.what());
 | 
			
		||||
        logError("protected lua call failed: ", e.what());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // pushes nil values if needed
 | 
			
		||||
| 
						 | 
				
			
			@ -457,7 +457,7 @@ int LuaInterface::luaScriptLoader(lua_State* L)
 | 
			
		|||
        g_lua.loadScript(fileName);
 | 
			
		||||
        return 1;
 | 
			
		||||
    } catch(LuaException& e) {
 | 
			
		||||
        logError("ERROR: failed to load script file '", fileName, "' :'", e.what());
 | 
			
		||||
        logError("failed to load script file '", fileName, "' :'", e.what());
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -489,7 +489,7 @@ int LuaInterface::luaCppFunctionCallback(lua_State* L)
 | 
			
		|||
        numRets = (*(funcPtr->get()))(&g_lua);
 | 
			
		||||
        assert(numRets == g_lua.stackSize());
 | 
			
		||||
    } catch(LuaException &e) {
 | 
			
		||||
        logError(e.what());
 | 
			
		||||
        logError("lua cpp callback failed: ", e.what());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return numRets;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,10 @@ LuaObject::LuaObject() : m_fieldsTableRef(-1)
 | 
			
		|||
 | 
			
		||||
LuaObject::~LuaObject()
 | 
			
		||||
{
 | 
			
		||||
    luaReleaseFieldsTable();
 | 
			
		||||
    releaseLuaFieldsTable();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LuaObject::luaReleaseFieldsTable()
 | 
			
		||||
void LuaObject::releaseLuaFieldsTable()
 | 
			
		||||
{
 | 
			
		||||
    if(m_fieldsTableRef != -1)
 | 
			
		||||
        g_lua.unref(m_fieldsTableRef);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,6 +15,8 @@ public:
 | 
			
		|||
    /// @return the number of results
 | 
			
		||||
    template<typename... T>
 | 
			
		||||
    int callLuaField(const std::string& field, const T&... args);
 | 
			
		||||
    template<typename R, typename... T>
 | 
			
		||||
    R callLuaField(const std::string& field, const T&... args);
 | 
			
		||||
 | 
			
		||||
    /// Sets a field in this lua object
 | 
			
		||||
    template<typename T>
 | 
			
		||||
| 
						 | 
				
			
			@ -25,7 +27,7 @@ public:
 | 
			
		|||
    T getLuaField(const std::string& key);
 | 
			
		||||
 | 
			
		||||
    /// Release fields table reference
 | 
			
		||||
    void luaReleaseFieldsTable();
 | 
			
		||||
    void releaseLuaFieldsTable();
 | 
			
		||||
 | 
			
		||||
    /// Sets a field from this lua object, the value must be on the stack
 | 
			
		||||
    void luaSetField(const std::string& key);
 | 
			
		||||
| 
						 | 
				
			
			@ -61,14 +63,30 @@ int LuaObject::callLuaField(const std::string& field, const T&... args) {
 | 
			
		|||
        g_lua.pushObject(asLuaObject());
 | 
			
		||||
        g_lua.getField(field);
 | 
			
		||||
 | 
			
		||||
        if(!g_lua.isNil()) {
 | 
			
		||||
            // the first argument is always this object (self)
 | 
			
		||||
            g_lua.insert(-2);
 | 
			
		||||
            g_lua.polymorphicPush(args...);
 | 
			
		||||
            return g_lua.protectedCall(1 + sizeof...(args));
 | 
			
		||||
    } else
 | 
			
		||||
        } else {
 | 
			
		||||
            g_lua.pop(2);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename R, typename... T>
 | 
			
		||||
R LuaObject::callLuaField(const std::string& field, const T&... args) {
 | 
			
		||||
    R result;
 | 
			
		||||
    int rets = callLuaField(field, args...);
 | 
			
		||||
    if(rets > 0) {
 | 
			
		||||
        assert(rets == 1);
 | 
			
		||||
        result = g_lua.polymorphicPop<R>();
 | 
			
		||||
    } else
 | 
			
		||||
        result = R();
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template<typename T>
 | 
			
		||||
void LuaObject::setLuaField(const std::string& key, const T& value) {
 | 
			
		||||
    g_lua.polymorphicPush(value);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,6 +42,20 @@ bool luavalue_cast(int index, double& d)
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// size_t
 | 
			
		||||
void push_luavalue(std::size_t s)
 | 
			
		||||
{
 | 
			
		||||
    push_luavalue((double)s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool luavalue_cast(int index, std::size_t& s)
 | 
			
		||||
{
 | 
			
		||||
    double d;
 | 
			
		||||
    bool ret = luavalue_cast(index, d);
 | 
			
		||||
    s = d;
 | 
			
		||||
    return ret;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// string
 | 
			
		||||
void push_luavalue(const char* cstr)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,10 @@ bool luavalue_cast(int index, int& i);
 | 
			
		|||
void push_luavalue(double d);
 | 
			
		||||
bool luavalue_cast(int index, double& d);
 | 
			
		||||
 | 
			
		||||
// size_t
 | 
			
		||||
void push_luavalue(std::size_t s);
 | 
			
		||||
bool luavalue_cast(int index, std::size_t& s);
 | 
			
		||||
 | 
			
		||||
// string
 | 
			
		||||
void push_luavalue(const char* cstr);
 | 
			
		||||
void push_luavalue(const std::string& str);
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +135,7 @@ bool luavalue_cast(int index, std::function<void(Args...)>& func) {
 | 
			
		|||
                                       "did you forget to hold a reference for that function?", 0);
 | 
			
		||||
                }
 | 
			
		||||
            } catch(std::exception& e) {
 | 
			
		||||
                logError(e.what());
 | 
			
		||||
                logError("lua function callback failed: ", e.what());
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        return true;
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +169,7 @@ luavalue_cast(int index, std::function<Ret(Args...)>& func) {
 | 
			
		|||
                                       "did you forget to hold a reference for that function?", 0);
 | 
			
		||||
                }
 | 
			
		||||
            } catch(std::exception& e) {
 | 
			
		||||
                logError(e.what());
 | 
			
		||||
                logError("lua function callback failed: ", e.what());
 | 
			
		||||
            }
 | 
			
		||||
            return Ret();
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size)
 | 
			
		|||
        uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH);
 | 
			
		||||
        if(m_inputMessage.getU32() != checksum) {
 | 
			
		||||
            // error
 | 
			
		||||
            logError("ERROR: got a network message with invalid checksum");
 | 
			
		||||
            logError("got a network message with invalid checksum");
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +93,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
 | 
			
		|||
    // FIXME: this function has not been tested yet
 | 
			
		||||
    uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH;
 | 
			
		||||
    if(messageSize % 8 != 0) {
 | 
			
		||||
        logError("ERROR: invalid encrypted network message");
 | 
			
		||||
        logError("invalid encrypted network message");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -116,7 +116,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage)
 | 
			
		|||
 | 
			
		||||
    int tmp = inputMessage.getU16();
 | 
			
		||||
    if(tmp > inputMessage.getMessageSize() - 4) {
 | 
			
		||||
        logDebug("ERROR: invalid decrypted a network message");
 | 
			
		||||
        logError("invalid decrypted a network message");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,6 @@
 | 
			
		|||
class OTMLDocument : public OTMLNode
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    OTMLDocument() { }
 | 
			
		||||
    virtual ~OTMLDocument() { }
 | 
			
		||||
 | 
			
		||||
    /// Create a new OTML document for filling it with nodes
 | 
			
		||||
| 
						 | 
				
			
			@ -24,6 +23,9 @@ public:
 | 
			
		|||
 | 
			
		||||
    /// Save this document to a file
 | 
			
		||||
    bool save(const std::string& fileName);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    OTMLDocument() { }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -161,7 +161,6 @@ enum PlatformEventType {
 | 
			
		|||
    EventMouseLeftButton         = 32,
 | 
			
		||||
    EventMouseRightButton        = 64,
 | 
			
		||||
    EventMouseMidButton          = 128,
 | 
			
		||||
    EventTextEnter               = 256,
 | 
			
		||||
    EventKeyDown                 = EventKeyboardAction | EventDown,
 | 
			
		||||
    EventKeyUp                   = EventKeyboardAction | EventUp,
 | 
			
		||||
    EventMouseMove               = EventMouseAction | 512,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -217,17 +217,17 @@ void Platform::init(PlatformListener* platformListener, const char *appName)
 | 
			
		|||
    // open display
 | 
			
		||||
    x11.display = XOpenDisplay(0);
 | 
			
		||||
    if(!x11.display)
 | 
			
		||||
        logFatal("FATAL ERROR: Failed to open X display");
 | 
			
		||||
        logFatal("Failed to open X display");
 | 
			
		||||
 | 
			
		||||
    // check if GLX is supported on this display
 | 
			
		||||
    if(!glXQueryExtension(x11.display, 0, 0))
 | 
			
		||||
        logFatal("FATAL ERROR: GLX not supported");
 | 
			
		||||
        logFatal("GLX not supported");
 | 
			
		||||
 | 
			
		||||
    // retrieve GLX version
 | 
			
		||||
    int glxMajor;
 | 
			
		||||
    int glxMinor;
 | 
			
		||||
    if(!glXQueryVersion(x11.display, &glxMajor, &glxMinor))
 | 
			
		||||
        logFatal("FATAL ERROR: Unable to query GLX version");
 | 
			
		||||
        logFatal("Unable to query GLX version");
 | 
			
		||||
    logInfo("GLX version ",glxMajor,".",glxMinor);
 | 
			
		||||
 | 
			
		||||
    // clipboard related atoms
 | 
			
		||||
| 
						 | 
				
			
			@ -313,6 +313,7 @@ void Platform::poll()
 | 
			
		|||
                inputEvent.ctrl = (event.xkey.state & ControlMask);
 | 
			
		||||
                inputEvent.shift = (event.xkey.state & ShiftMask);
 | 
			
		||||
                inputEvent.alt = (event.xkey.state & Mod1Mask);
 | 
			
		||||
                inputEvent.keychar = 0;
 | 
			
		||||
 | 
			
		||||
                // fire enter text event
 | 
			
		||||
                if(event.type == KeyPress && !inputEvent.ctrl && !inputEvent.alt) {
 | 
			
		||||
| 
						 | 
				
			
			@ -325,7 +326,7 @@ void Platform::poll()
 | 
			
		|||
                    }
 | 
			
		||||
 | 
			
		||||
                    if(len > 0 &&
 | 
			
		||||
                       // for some reason these keys produces characters and we don't want that
 | 
			
		||||
                       // these keys produces characters that we don't want to capture
 | 
			
		||||
                       keysym != XK_BackSpace &&
 | 
			
		||||
                       keysym != XK_Return &&
 | 
			
		||||
                       keysym != XK_Delete &&
 | 
			
		||||
| 
						 | 
				
			
			@ -333,10 +334,7 @@ void Platform::poll()
 | 
			
		|||
                       (uchar)(buf[0]) >= 32
 | 
			
		||||
                    ) {
 | 
			
		||||
                        //logDebug("char: ", buf[0], " code: ", (uint)buf[0]);
 | 
			
		||||
                        inputEvent.type = EventTextEnter;
 | 
			
		||||
                        inputEvent.keychar = buf[0];
 | 
			
		||||
                        inputEvent.keycode = KC_UNKNOWN;
 | 
			
		||||
                        m_listener->onPlatformEvent(inputEvent);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -344,13 +342,19 @@ void Platform::poll()
 | 
			
		|||
                event.xkey.state &= ~(ShiftMask | LockMask);
 | 
			
		||||
                len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, 0);
 | 
			
		||||
 | 
			
		||||
                // fire key up/down event
 | 
			
		||||
                if(x11.keyMap.find(keysym) != x11.keyMap.end()) {
 | 
			
		||||
                if(inputEvent.keychar == 0)
 | 
			
		||||
                    inputEvent.keychar = (len > 0) ? buf[0] : 0;
 | 
			
		||||
 | 
			
		||||
                if(x11.keyMap.find(keysym) != x11.keyMap.end())
 | 
			
		||||
                    inputEvent.keycode = x11.keyMap[keysym];
 | 
			
		||||
                else
 | 
			
		||||
                    inputEvent.keycode = KC_UNKNOWN;
 | 
			
		||||
 | 
			
		||||
                inputEvent.keycode = x11.keyMap[keysym];
 | 
			
		||||
                inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp;
 | 
			
		||||
                    inputEvent.keychar = (len > 0) ? buf[0] : 0;
 | 
			
		||||
 | 
			
		||||
                if(inputEvent.keycode != KC_UNKNOWN || inputEvent.keychar != 0)
 | 
			
		||||
                    m_listener->onPlatformEvent(inputEvent);
 | 
			
		||||
                }
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case ButtonPress:
 | 
			
		||||
| 
						 | 
				
			
			@ -480,12 +484,12 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i
 | 
			
		|||
    // choose OpenGL, RGBA, double buffered, visual
 | 
			
		||||
    x11.visual = glXChooseVisual(x11.display, DefaultScreen(x11.display), attrList);
 | 
			
		||||
    if(!x11.visual)
 | 
			
		||||
        logFatal("FATAL ERROR: RGBA/Double buffered visual not supported");
 | 
			
		||||
        logFatal("RGBA/Double buffered visual not supported");
 | 
			
		||||
 | 
			
		||||
    // create GLX context
 | 
			
		||||
    x11.glxContext = glXCreateContext(x11.display, x11.visual, 0, GL_TRUE);
 | 
			
		||||
    if(!x11.glxContext)
 | 
			
		||||
        logFatal("FATAL ERROR: Unable to create GLX context");
 | 
			
		||||
        logFatal("Unable to create GLX context");
 | 
			
		||||
 | 
			
		||||
    // color map
 | 
			
		||||
    x11.colormap  = XCreateColormap(x11.display,
 | 
			
		||||
| 
						 | 
				
			
			@ -518,7 +522,7 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i
 | 
			
		|||
                             &wa);
 | 
			
		||||
 | 
			
		||||
    if(!x11.window)
 | 
			
		||||
        logFatal("FATAL ERROR: Unable to create X window");
 | 
			
		||||
        logFatal("Unable to create X window");
 | 
			
		||||
 | 
			
		||||
    //  create input context (to have better key input handling)
 | 
			
		||||
    if(XSupportsLocale()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -530,11 +534,11 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i
 | 
			
		|||
                                    XIMPreeditNothing | XIMStatusNothing,
 | 
			
		||||
                                    XNClientWindow, x11.window, NULL);
 | 
			
		||||
            if(!x11.xic)
 | 
			
		||||
                logError("ERROR: Unable to create the input context");
 | 
			
		||||
                logError("Unable to create the input context");
 | 
			
		||||
        } else
 | 
			
		||||
            logError("ERROR: Failed to open an input method");
 | 
			
		||||
            logError("Failed to open an input method");
 | 
			
		||||
    } else
 | 
			
		||||
        logError("ERROR: X11 does not support the current locale");
 | 
			
		||||
        logError("X11 does not support the current locale");
 | 
			
		||||
 | 
			
		||||
    if(!x11.xic)
 | 
			
		||||
        logWarning("Input of special keys maybe messed up because we couldn't create an input context");
 | 
			
		||||
| 
						 | 
				
			
			@ -823,6 +827,6 @@ std::string Platform::getAppUserDir()
 | 
			
		|||
    std::stringstream sdir;
 | 
			
		||||
    sdir << PHYSFS_getUserDir() << "." << x11.appName;
 | 
			
		||||
    if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST))
 | 
			
		||||
        logError("ERROR: Couldn't create directory for saving configuration file. (",sdir.str(),")");
 | 
			
		||||
        logError("Couldn't create directory for saving configuration file. (",sdir.str(),")");
 | 
			
		||||
    return sdir.str();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,7 +9,8 @@ enum UIWidgetType {
 | 
			
		|||
    UITypeButton,
 | 
			
		||||
    UITypeLineEdit,
 | 
			
		||||
    UITypeWindow,
 | 
			
		||||
    UITypeList
 | 
			
		||||
    UITypeList,
 | 
			
		||||
    UITypeConsole
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum FocusReason {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,6 +13,7 @@ class UILabel;
 | 
			
		|||
class UIButton;
 | 
			
		||||
class UILineEdit;
 | 
			
		||||
class UIWindow;
 | 
			
		||||
class UIConsole;
 | 
			
		||||
 | 
			
		||||
typedef std::shared_ptr<UIWidget> UIWidgetPtr;
 | 
			
		||||
typedef std::weak_ptr<UIWidget> UIWidgetWeakPtr;
 | 
			
		||||
| 
						 | 
				
			
			@ -25,5 +26,6 @@ typedef std::shared_ptr<UILabel> UILabelPtr;
 | 
			
		|||
typedef std::shared_ptr<UIButton> UIButtonPtr;
 | 
			
		||||
typedef std::shared_ptr<UILineEdit> UILineEditPtr;
 | 
			
		||||
typedef std::shared_ptr<UIWindow> UIWindowPtr;
 | 
			
		||||
typedef std::shared_ptr<UIConsole> UIConsolePtr;
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,23 +8,32 @@ bool UIAnchorLayout::addAnchor(const UIWidgetPtr& anchoredWidget, AnchorPoint an
 | 
			
		|||
 | 
			
		||||
    /*
 | 
			
		||||
    if(!anchorLineWidget) {
 | 
			
		||||
        logError("ERROR: could not find the widget to anchor on, wrong id?");
 | 
			
		||||
        logError("could not find the widget to anchor on, wrong id?");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    // we can never anchor with itself
 | 
			
		||||
    if(anchoredWidget == anchorLineWidget) {
 | 
			
		||||
        logError("ERROR: anchoring with itself is not possible");
 | 
			
		||||
        logError("anchoring with itself is not possible");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // we must never anchor to an anchor child
 | 
			
		||||
    if(anchoredWidget && hasWidgetInAnchorTree(anchorLineWidget, anchoredWidget)) {
 | 
			
		||||
        logError("ERROR: anchors is miss configured, you must never make an anchor chains in loops");
 | 
			
		||||
        logError("anchors is miss configured, you must never make an anchor chains in loops");
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // avoid duplicated anchors
 | 
			
		||||
    for(auto it = m_anchors.begin(); it != m_anchors.end(); ++it) {
 | 
			
		||||
        const UIAnchor& otherAnchor = *it;
 | 
			
		||||
        if(otherAnchor.getAnchoredWidget() == anchoredWidget && otherAnchor.getAnchoredEdge() == anchoredEdge) {
 | 
			
		||||
            m_anchors.erase(it);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // setup the anchor
 | 
			
		||||
    m_anchors.push_back(anchor);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@
 | 
			
		|||
#include <framework/graphics/font.h>
 | 
			
		||||
#include <framework/otml/otmlnode.h>
 | 
			
		||||
#include <framework/luascript/luainterface.h>
 | 
			
		||||
#include <framework/graphics/graphics.h>
 | 
			
		||||
 | 
			
		||||
UIButton::UIButton(): UIWidget(UITypeButton)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -25,8 +26,8 @@ void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
 | 
			
		||||
    for(int i=0; i<3; ++i) {
 | 
			
		||||
        m_statesStyle[i].image = m_image;
 | 
			
		||||
        m_statesStyle[i].color = m_color;
 | 
			
		||||
        m_statesStyle[i].fontColor = m_fontColor;
 | 
			
		||||
        m_statesStyle[i].color = m_backgroundColor;
 | 
			
		||||
        m_statesStyle[i].foregroundColor = m_foregroundColor;
 | 
			
		||||
        m_statesStyle[i].textTranslate = Point(0,0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +41,8 @@ void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
    m_text = styleNode->valueAt("text", fw::empty_string);
 | 
			
		||||
 | 
			
		||||
    if(OTMLNodePtr node = styleNode->get("onClick")) {
 | 
			
		||||
        g_lua.loadFunction(node->value<std::string>(), "@" + node->source() + "[" + node->tag() + "]");
 | 
			
		||||
        luaSetField("onClick");
 | 
			
		||||
        g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
 | 
			
		||||
        luaSetField(node->tag());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -52,20 +53,24 @@ void UIButton::loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& s
 | 
			
		|||
    if(OTMLNodePtr node = stateStyleNode->get("image"))
 | 
			
		||||
        stateStyle.image = Image::loadFromOTML(node);
 | 
			
		||||
    stateStyle.textTranslate = stateStyleNode->valueAt("text-translate", Point());
 | 
			
		||||
    stateStyle.color = stateStyleNode->valueAt("font-color", m_fontColor);
 | 
			
		||||
    stateStyle.color = stateStyleNode->valueAt("color", m_color);
 | 
			
		||||
    stateStyle.color = stateStyleNode->valueAt("font-color", m_foregroundColor);
 | 
			
		||||
    stateStyle.color = stateStyleNode->valueAt("color", m_backgroundColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIButton::render()
 | 
			
		||||
{
 | 
			
		||||
    UIWidget::render();
 | 
			
		||||
 | 
			
		||||
    const ButtonStateStyle& currentStyle = m_statesStyle[m_state];
 | 
			
		||||
    Rect textRect = getGeometry();
 | 
			
		||||
 | 
			
		||||
    if(currentStyle.image)
 | 
			
		||||
    if(currentStyle.image) {
 | 
			
		||||
        g_graphics.bindColor(currentStyle.color);
 | 
			
		||||
        currentStyle.image->draw(textRect);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    textRect.translate(currentStyle.textTranslate);
 | 
			
		||||
    getFont()->renderText(m_text, textRect, AlignCenter, currentStyle.fontColor);
 | 
			
		||||
    m_font->renderText(m_text, textRect, AlignCenter, currentStyle.foregroundColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIButton::onHoverChange(UIHoverEvent& event)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,7 +8,7 @@ class UIButton : public UIWidget
 | 
			
		|||
    struct ButtonStateStyle {
 | 
			
		||||
        ImagePtr image;
 | 
			
		||||
        Point textTranslate;
 | 
			
		||||
        Color fontColor;
 | 
			
		||||
        Color foregroundColor;
 | 
			
		||||
        Color color;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,7 +10,6 @@ UILabel::UILabel() : UIWidget(UITypeLabel)
 | 
			
		|||
UILabelPtr UILabel::create()
 | 
			
		||||
{
 | 
			
		||||
    UILabelPtr label(new UILabel);
 | 
			
		||||
    label->setStyle("Label");
 | 
			
		||||
    return label;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -23,17 +22,23 @@ void UILabel::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
    if(styleNode->hasChildAt("align"))
 | 
			
		||||
        m_align = fw::translateAlignment(styleNode->valueAt("align"));
 | 
			
		||||
 | 
			
		||||
    // auto resize if no size supplied
 | 
			
		||||
    if(!m_text.empty() && !getGeometry().isValid())
 | 
			
		||||
        resizeToText();
 | 
			
		||||
    // auto resize if needed
 | 
			
		||||
    if(!m_text.empty() && !m_rect.isValid()) {
 | 
			
		||||
        Size textSize = m_font->calculateTextRectSize(m_text);
 | 
			
		||||
        if(m_rect.width() <= 0)
 | 
			
		||||
            m_rect.setWidth(textSize.width());
 | 
			
		||||
        if(m_rect.height() <= 0)
 | 
			
		||||
            m_rect.setHeight(textSize.height());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UILabel::render()
 | 
			
		||||
{
 | 
			
		||||
    m_font->renderText(m_text, m_rect, m_align, m_fontColor);
 | 
			
		||||
    UIWidget::render();
 | 
			
		||||
    m_font->renderText(m_text, m_rect, m_align, m_foregroundColor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UILabel::resizeToText()
 | 
			
		||||
{
 | 
			
		||||
    resize(getFont()->calculateTextRectSize(m_text));
 | 
			
		||||
    resize(m_font->calculateTextRectSize(m_text));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,8 @@ UILineEdit::UILineEdit() : UIWidget(UITypeLabel)
 | 
			
		|||
    m_textHorizontalMargin = 3;
 | 
			
		||||
    m_focusable = true;
 | 
			
		||||
    blinkCursor();
 | 
			
		||||
 | 
			
		||||
    m_onAction = [this]() { this->callLuaField("onAction"); };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UILineEditPtr UILineEdit::create()
 | 
			
		||||
| 
						 | 
				
			
			@ -26,6 +28,11 @@ void UILineEdit::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
    UIWidget::loadStyleFromOTML(styleNode);
 | 
			
		||||
 | 
			
		||||
    setText(styleNode->valueAt("text", getText()));
 | 
			
		||||
 | 
			
		||||
    if(OTMLNodePtr node = styleNode->get("onAction")) {
 | 
			
		||||
        g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]");
 | 
			
		||||
        luaSetField(node->tag());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UILineEdit::render()
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +60,7 @@ void UILineEdit::render()
 | 
			
		|||
                cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight());
 | 
			
		||||
            else
 | 
			
		||||
                cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight());
 | 
			
		||||
            g_graphics.drawFilledRect(cursorRect, m_color);
 | 
			
		||||
            g_graphics.drawFilledRect(cursorRect);
 | 
			
		||||
        } else if(ticks - m_cursorTicks >= 2*delay) {
 | 
			
		||||
            m_cursorTicks = ticks;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +262,7 @@ void UILineEdit::setCursorPos(int pos)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UILineEdit::enableCursor(bool enable)
 | 
			
		||||
void UILineEdit::setCursorEnabled(bool enable)
 | 
			
		||||
{
 | 
			
		||||
    if(enable) {
 | 
			
		||||
        m_cursorPos = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -357,7 +364,10 @@ void UILineEdit::onKeyPress(UIKeyEvent& event)
 | 
			
		|||
        setCursorPos(0);
 | 
			
		||||
    else if(event.keyCode() == KC_END) // move cursor to last character
 | 
			
		||||
        setCursorPos(m_text.length());
 | 
			
		||||
    else if(event.keyChar() != 0) {
 | 
			
		||||
    else if(event.keyCode() == KC_RETURN) {
 | 
			
		||||
        if(m_onAction)
 | 
			
		||||
            m_onAction();
 | 
			
		||||
    } else if(event.keyChar() != 0) {
 | 
			
		||||
        if(event.keyCode() != KC_TAB && event.keyCode() != KC_RETURN)
 | 
			
		||||
            appendCharacter(event.keyChar());
 | 
			
		||||
        else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,8 +18,9 @@ public:
 | 
			
		|||
    void setText(const std::string& text);
 | 
			
		||||
    void setAlign(AlignmentFlag align);
 | 
			
		||||
    void setCursorPos(int pos);
 | 
			
		||||
    void enableCursor(bool enable = true);
 | 
			
		||||
    void setCursorEnabled(bool enable = true);
 | 
			
		||||
 | 
			
		||||
    void clearText() { setText(""); }
 | 
			
		||||
    void moveCursor(bool right);
 | 
			
		||||
    void appendCharacter(char c);
 | 
			
		||||
    void removeCharacter(bool right);
 | 
			
		||||
| 
						 | 
				
			
			@ -45,6 +46,7 @@ private:
 | 
			
		|||
    int m_startRenderPos;
 | 
			
		||||
    int m_cursorTicks;
 | 
			
		||||
    int m_textHorizontalMargin;
 | 
			
		||||
    SimpleCallback m_onAction;
 | 
			
		||||
 | 
			
		||||
    std::vector<Rect> m_glyphsCoords;
 | 
			
		||||
    std::vector<Rect> m_glyphsTexCoords;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ bool UIManager::importStyles(const std::string& file)
 | 
			
		|||
            importStyleFromOTML(styleNode);
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: failed to import ui styles from '", file, "':\n", e.what());
 | 
			
		||||
        logError("failed to import ui styles from '", file, "':\n", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
 | 
			
		||||
    auto it = m_styles.find(name);
 | 
			
		||||
    if(it != m_styles.end())
 | 
			
		||||
        logWarning("WARNING: style '", name, "' is being redefined");
 | 
			
		||||
        logWarning("style '", name, "' is being redefined");
 | 
			
		||||
 | 
			
		||||
    OTMLNodePtr style = getStyle(base)->clone();
 | 
			
		||||
    style->merge(styleNode);
 | 
			
		||||
| 
						 | 
				
			
			@ -158,11 +158,9 @@ UIWidgetPtr UIManager::loadUI(const std::string& file)
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // schedule onLoad events
 | 
			
		||||
        widget->load();
 | 
			
		||||
        return widget;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: failed to load ui from '", file, "':\n", e.what());
 | 
			
		||||
        logError("failed to load ui from '", file, "':\n", e.what());
 | 
			
		||||
        return nullptr;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,8 +21,8 @@ UIWidget::UIWidget(UIWidgetType type)
 | 
			
		|||
    m_updateScheduled = false;
 | 
			
		||||
    m_opacity = 255;
 | 
			
		||||
    m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = 0;
 | 
			
		||||
    m_color = Color::white;
 | 
			
		||||
    m_fontColor = Color::white;
 | 
			
		||||
    m_backgroundColor = Color::white;
 | 
			
		||||
    m_foregroundColor = Color::white;
 | 
			
		||||
 | 
			
		||||
    // generate an unique id, this is need because anchored layouts find widgets by id
 | 
			
		||||
    static unsigned long id = 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -33,13 +33,12 @@ UIWidget::~UIWidget()
 | 
			
		|||
{
 | 
			
		||||
    //logTraceDebug(m_id);
 | 
			
		||||
    if(!m_destroyed)
 | 
			
		||||
        logWarning("WARNING: widget '", m_id, "' was destructed without being explicit destroyed");
 | 
			
		||||
        logWarning("widget '", m_id, "' was destructed without being explicit destroyed");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UIWidgetPtr UIWidget::create()
 | 
			
		||||
{
 | 
			
		||||
    UIWidgetPtr widget(new UIWidget);
 | 
			
		||||
    //widget->setStyle("Widget");
 | 
			
		||||
    return widget;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -48,6 +47,8 @@ void UIWidget::destroy()
 | 
			
		|||
    //TODO: onDestroy event
 | 
			
		||||
    // destroy only once
 | 
			
		||||
    if(!m_destroyed) {
 | 
			
		||||
        releaseLuaFieldsTable();
 | 
			
		||||
 | 
			
		||||
        // clear additional reference
 | 
			
		||||
        m_lockedWidgets.clear();
 | 
			
		||||
        m_focusedChild.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -68,7 +69,7 @@ void UIWidget::destroy()
 | 
			
		|||
        m_enabled = false;
 | 
			
		||||
        m_visible = false;
 | 
			
		||||
    } else
 | 
			
		||||
        logWarning("WARNING: attempt to destroy widget '", m_id, "' again");
 | 
			
		||||
        logWarning("attempt to destroy widget '", m_id, "' again");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::destroyCheck()
 | 
			
		||||
| 
						 | 
				
			
			@ -81,21 +82,7 @@ void UIWidget::destroyCheck()
 | 
			
		|||
 | 
			
		||||
    // check for leaks upon widget destruction
 | 
			
		||||
    if(realUseCount > 0)
 | 
			
		||||
        logWarning("WARNING: destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::load()
 | 
			
		||||
{
 | 
			
		||||
    for(const UIWidgetPtr& child : m_children)
 | 
			
		||||
        child->load();
 | 
			
		||||
 | 
			
		||||
    // schedule onLoad
 | 
			
		||||
    UIWidgetPtr self = asUIWidget();
 | 
			
		||||
    g_dispatcher.addEvent([self]() {
 | 
			
		||||
        // this widget could be destroyed before the event happens
 | 
			
		||||
        if(!self->isDestroyed())
 | 
			
		||||
            self->callLuaField("onLoad");
 | 
			
		||||
    });
 | 
			
		||||
        logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		||||
| 
						 | 
				
			
			@ -120,12 +107,12 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
            setFont(g_fonts.getFont(node->value()));
 | 
			
		||||
        }
 | 
			
		||||
        // font color
 | 
			
		||||
        else if(node->tag() == "font-color") {
 | 
			
		||||
            setFontColor(node->value<Color>());
 | 
			
		||||
        else if(node->tag() == "color") {
 | 
			
		||||
            setForegroundColor(node->value<Color>());
 | 
			
		||||
        }
 | 
			
		||||
        // color
 | 
			
		||||
        else if(node->tag() == "color") {
 | 
			
		||||
            setColor(node->value<Color>());
 | 
			
		||||
        else if(node->tag() == "background-color") {
 | 
			
		||||
            setBackgroundColor(node->value<Color>());
 | 
			
		||||
        }
 | 
			
		||||
        // opacity
 | 
			
		||||
        else if(node->tag() == "opacity") {
 | 
			
		||||
| 
						 | 
				
			
			@ -197,9 +184,6 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode)
 | 
			
		|||
            luaSetField("onLoad");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(!m_font)
 | 
			
		||||
        m_font = g_fonts.getDefaultFont();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::render()
 | 
			
		||||
| 
						 | 
				
			
			@ -215,9 +199,13 @@ void UIWidget::render()
 | 
			
		|||
            if(child->getOpacity() < oldOpacity)
 | 
			
		||||
                g_graphics.setOpacity(child->getOpacity());
 | 
			
		||||
 | 
			
		||||
            g_graphics.bindColor(child->getColor());
 | 
			
		||||
            g_graphics.bindColor(child->getBackgroundColor());
 | 
			
		||||
            child->render();
 | 
			
		||||
 | 
			
		||||
            // debug draw box
 | 
			
		||||
            //g_graphics.bindColor(Color::green);
 | 
			
		||||
            //g_graphics.drawBoundingRect(child->getGeometry());
 | 
			
		||||
 | 
			
		||||
            g_graphics.setOpacity(oldOpacity);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -227,8 +215,10 @@ void UIWidget::updateGeometry()
 | 
			
		|||
{
 | 
			
		||||
    assert(!m_destroyed);
 | 
			
		||||
 | 
			
		||||
    if(UILayoutPtr layout = getLayout())
 | 
			
		||||
    if(UILayoutPtr layout = getLayout()) {
 | 
			
		||||
        layout->updateWidget(asUIWidget());
 | 
			
		||||
        layout->updateWidgetChildren(asUIWidget());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::setParent(const UIWidgetPtr& parent)
 | 
			
		||||
| 
						 | 
				
			
			@ -260,7 +250,7 @@ void UIWidget::setStyle(const std::string& styleName)
 | 
			
		|||
        // forces layout recalculation
 | 
			
		||||
        updateGeometry();
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: couldn't change widget '", m_id, "' style: ", e.what());
 | 
			
		||||
        logError("couldn't change widget '", m_id, "' style: ", e.what());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -287,15 +277,6 @@ void UIWidget::setGeometry(const Rect& rect)
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::lock()
 | 
			
		||||
{
 | 
			
		||||
    assert(!m_destroyed);
 | 
			
		||||
 | 
			
		||||
    UIWidgetPtr parent = getParent();
 | 
			
		||||
    if(parent)
 | 
			
		||||
        parent->lockChild(asUIWidget());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool UIWidget::isEnabled()
 | 
			
		||||
{
 | 
			
		||||
    if(!m_enabled)
 | 
			
		||||
| 
						 | 
				
			
			@ -401,7 +382,7 @@ UIWidgetPtr UIWidget::getChildByPos(const Point& childPos)
 | 
			
		|||
 | 
			
		||||
    for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) {
 | 
			
		||||
        const UIWidgetPtr& widget = (*it);
 | 
			
		||||
        if(widget->getGeometry().contains(childPos))
 | 
			
		||||
        if(widget->isVisible() && widget->getGeometry().contains(childPos))
 | 
			
		||||
            return widget;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -533,14 +514,40 @@ void UIWidget::addChild(const UIWidgetPtr& childToAdd)
 | 
			
		|||
    m_children.push_back(childToAdd);
 | 
			
		||||
    childToAdd->setParent(asUIWidget());
 | 
			
		||||
 | 
			
		||||
    // updates child position
 | 
			
		||||
    childToAdd->updateGeometry();
 | 
			
		||||
    // updates geometry
 | 
			
		||||
    updateGeometry();
 | 
			
		||||
 | 
			
		||||
    // focus it if there is no focused child yet
 | 
			
		||||
    if(!m_focusedChild && childToAdd->isFocusable())
 | 
			
		||||
        focusChild(childToAdd, ActiveFocusReason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index)
 | 
			
		||||
{
 | 
			
		||||
    assert(!m_destroyed);
 | 
			
		||||
 | 
			
		||||
    if(!childToInsert)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    assert(!hasChild(childToInsert));
 | 
			
		||||
 | 
			
		||||
    if(index < 0)
 | 
			
		||||
        index = m_children.size() + index -1;
 | 
			
		||||
 | 
			
		||||
    assert((uint)index <= m_children.size());
 | 
			
		||||
 | 
			
		||||
    auto it = m_children.begin() + index;
 | 
			
		||||
    m_children.insert(it, childToInsert);
 | 
			
		||||
    childToInsert->setParent(asUIWidget());
 | 
			
		||||
 | 
			
		||||
    // updates geometry
 | 
			
		||||
    updateGeometry();
 | 
			
		||||
 | 
			
		||||
    // focus it if there is no focused child yet
 | 
			
		||||
    if(!m_focusedChild && childToInsert->isFocusable())
 | 
			
		||||
        focusChild(childToInsert, ActiveFocusReason);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::removeChild(const UIWidgetPtr& childToRemove)
 | 
			
		||||
{
 | 
			
		||||
    assert(!m_destroyed);
 | 
			
		||||
| 
						 | 
				
			
			@ -612,6 +619,9 @@ void UIWidget::lockChild(const UIWidgetPtr& childToLock)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    m_lockedWidgets.push_front(childToLock);
 | 
			
		||||
 | 
			
		||||
    // move locked child to top
 | 
			
		||||
    moveChildToTop(childToLock);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock)
 | 
			
		||||
| 
						 | 
				
			
			@ -619,8 +629,9 @@ void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock)
 | 
			
		|||
    assert(hasChild(childToUnlock));
 | 
			
		||||
 | 
			
		||||
    auto it = std::find(m_lockedWidgets.begin(), m_lockedWidgets.end(), childToUnlock);
 | 
			
		||||
    if(it != m_lockedWidgets.end()) {
 | 
			
		||||
    if(it != m_lockedWidgets.end())
 | 
			
		||||
        m_lockedWidgets.erase(it);
 | 
			
		||||
 | 
			
		||||
    UIWidgetPtr newLockedWidget;
 | 
			
		||||
    if(m_lockedWidgets.size() > 0)
 | 
			
		||||
        newLockedWidget = m_lockedWidgets.front();
 | 
			
		||||
| 
						 | 
				
			
			@ -634,7 +645,6 @@ void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock)
 | 
			
		|||
        } else
 | 
			
		||||
            child->setEnabled(true);
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UIWidget::addAnchor(AnchorPoint edge, const std::string& targetId, AnchorPoint targetEdge)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,12 +15,12 @@ public:
 | 
			
		|||
 | 
			
		||||
    static UIWidgetPtr create();
 | 
			
		||||
 | 
			
		||||
    /// Must be called just after the widget creation
 | 
			
		||||
    virtual void setup() { }
 | 
			
		||||
 | 
			
		||||
    /// Remove this widget from parent then destroy it and its children
 | 
			
		||||
    virtual void destroy();
 | 
			
		||||
 | 
			
		||||
    /// Called after the widget is loaded from OTML file, to execute onLoad event
 | 
			
		||||
    virtual void load();
 | 
			
		||||
 | 
			
		||||
    /// Load style from otml node
 | 
			
		||||
    virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +50,8 @@ public:
 | 
			
		|||
    void setImage(const ImagePtr& image) { m_image = image; }
 | 
			
		||||
    virtual void setFont(const FontPtr& font) { m_font = font; }
 | 
			
		||||
    void setOpacity(int opacity) { m_opacity = opacity; }
 | 
			
		||||
    void setColor(const Color& color) { m_color = color; }
 | 
			
		||||
    void setFontColor(const Color& color) { m_fontColor = color; }
 | 
			
		||||
    void setBackgroundColor(const Color& color) { m_backgroundColor = color; }
 | 
			
		||||
    void setForegroundColor(const Color& color) { m_foregroundColor = color; }
 | 
			
		||||
    void setMarginLeft(int margin) { m_marginLeft = margin; updateGeometry(); }
 | 
			
		||||
    void setMarginRight(int margin) { m_marginRight = margin; updateGeometry(); }
 | 
			
		||||
    void setMarginTop(int margin) { m_marginTop = margin; updateGeometry(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,6 @@ public:
 | 
			
		|||
    void show() { setVisible(true); }
 | 
			
		||||
    void disable() { setEnabled(false); }
 | 
			
		||||
    void enable() { setEnabled(true); }
 | 
			
		||||
    void lock();
 | 
			
		||||
 | 
			
		||||
    bool isEnabled();
 | 
			
		||||
    bool isExplicitlyEnabled() const { return m_enabled; }
 | 
			
		||||
| 
						 | 
				
			
			@ -88,8 +87,8 @@ public:
 | 
			
		|||
 | 
			
		||||
    ImagePtr getImage() const { return m_image; }
 | 
			
		||||
    FontPtr getFont() const { return m_font; }
 | 
			
		||||
    Color getFontColor() const { return m_fontColor; }
 | 
			
		||||
    Color getColor() const { return m_color; }
 | 
			
		||||
    Color getForegroundColor() const { return m_foregroundColor; }
 | 
			
		||||
    Color getBackgroundColor() const { return m_backgroundColor; }
 | 
			
		||||
    int getOpacity() const { return m_opacity; }
 | 
			
		||||
    int getMarginLeft() const { return m_marginLeft; }
 | 
			
		||||
    int getMarginRight() const { return m_marginRight; }
 | 
			
		||||
| 
						 | 
				
			
			@ -108,6 +107,7 @@ public:
 | 
			
		|||
    UIWidgetPtr backwardsGetWidgetById(const std::string& id);
 | 
			
		||||
 | 
			
		||||
    void addChild(const UIWidgetPtr& childToAdd);
 | 
			
		||||
    void insertChild(const UIWidgetPtr& childToInsert, int index);
 | 
			
		||||
    void removeChild(const UIWidgetPtr& childToRemove);
 | 
			
		||||
    void focusChild(const UIWidgetPtr& childToFocus, FocusReason reason);
 | 
			
		||||
    void focusNextChild(FocusReason reason);
 | 
			
		||||
| 
						 | 
				
			
			@ -169,8 +169,8 @@ protected:
 | 
			
		|||
    ImagePtr m_image;
 | 
			
		||||
    FontPtr m_font;
 | 
			
		||||
    int m_opacity;
 | 
			
		||||
    Color m_color;
 | 
			
		||||
    Color m_fontColor;
 | 
			
		||||
    Color m_backgroundColor;
 | 
			
		||||
    Color m_foregroundColor;
 | 
			
		||||
    int m_marginLeft;
 | 
			
		||||
    int m_marginRight;
 | 
			
		||||
    int m_marginTop;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@ void UIWindow::render()
 | 
			
		|||
            headTextRect.addLeft(-m_headMargin);
 | 
			
		||||
        else if(m_titleAlign & AlignRight)
 | 
			
		||||
            headTextRect.addRight(-m_headMargin);
 | 
			
		||||
        m_font->renderText(m_title, headTextRect, m_titleAlign, m_fontColor);
 | 
			
		||||
        m_font->renderText(m_title, headTextRect, m_titleAlign, m_foregroundColor);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // draw window body
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
#define COLOR_H
 | 
			
		||||
 | 
			
		||||
#include "types.h"
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
 | 
			
		||||
typedef uint32 RGBA;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,10 +69,19 @@ inline std::istream& operator>>(std::istream& in, Color& color)
 | 
			
		|||
    using namespace std;
 | 
			
		||||
 | 
			
		||||
    if(in.get() == '#') {
 | 
			
		||||
        uint32 tmp;
 | 
			
		||||
        in >> hex >> tmp;
 | 
			
		||||
        color.setABGR(tmp);
 | 
			
		||||
        in >> dec;
 | 
			
		||||
        std::string tmp;
 | 
			
		||||
        in >> tmp;
 | 
			
		||||
 | 
			
		||||
        if(tmp.length() == 6 || tmp.length() == 8) {
 | 
			
		||||
            color.setRed((uint8)fw::hex2dec(tmp.substr(0, 2)));
 | 
			
		||||
            color.setGreen((uint8)fw::hex2dec(tmp.substr(2, 2)));
 | 
			
		||||
            color.setBlue((uint8)fw::hex2dec(tmp.substr(4, 2)));
 | 
			
		||||
            if(tmp.length() == 8)
 | 
			
		||||
                color.setAlpha((uint8)fw::hex2dec(tmp.substr(6, 2)));
 | 
			
		||||
            else
 | 
			
		||||
                color.setAlpha(255);
 | 
			
		||||
        } else
 | 
			
		||||
            in.seekg(-tmp.length()-1, ios_base::cur);
 | 
			
		||||
    }
 | 
			
		||||
    return in;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +0,0 @@
 | 
			
		|||
#include "logger.h"
 | 
			
		||||
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
 | 
			
		||||
void Logger::log(LogLevel level, const std::string& message, std::string prettyFunction)
 | 
			
		||||
{
 | 
			
		||||
    if(!prettyFunction.empty()) {
 | 
			
		||||
        prettyFunction = prettyFunction.substr(0, prettyFunction.find_first_of('('));
 | 
			
		||||
        if(prettyFunction.find_last_of(' ') != std::string::npos)
 | 
			
		||||
            prettyFunction = prettyFunction.substr(prettyFunction.find_last_of(' ') + 1);
 | 
			
		||||
        if(!prettyFunction.empty())
 | 
			
		||||
            std::cout << "[" << prettyFunction << "] ";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cout << message << std::endl;
 | 
			
		||||
 | 
			
		||||
    if(level == LogFatal)
 | 
			
		||||
        exit(-1);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,33 +0,0 @@
 | 
			
		|||
#ifndef LOGGER_H
 | 
			
		||||
#define LOGGER_H
 | 
			
		||||
 | 
			
		||||
#include "tools.h"
 | 
			
		||||
 | 
			
		||||
//TODO: a real logger
 | 
			
		||||
class Logger
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    enum LogLevel {
 | 
			
		||||
        LogDebug = 0,
 | 
			
		||||
        LogInfo,
 | 
			
		||||
        LogWarning,
 | 
			
		||||
        LogError,
 | 
			
		||||
        LogFatal
 | 
			
		||||
    };
 | 
			
		||||
    static void log(LogLevel level, const std::string& message, std::string prettyFunction = "");
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// specialized logging
 | 
			
		||||
#define logDebug(...) Logger::log(Logger::LogDebug, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logInfo(...) Logger::log(Logger::LogInfo, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logWarning(...) Logger::log(Logger::LogWarning, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logError(...) Logger::log(Logger::LogError, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
#define logFatal(...) Logger::log(Logger::LogFatal, fw::mkstr(__VA_ARGS__))
 | 
			
		||||
 | 
			
		||||
#define logTrace() Logger::log(Logger::LogDebug, "", __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceDebug(...) Logger::log(Logger::LogDebug, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceInfo(...) Logger::log(Logger::LogInfo, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceWarning(...) log(Logger::LogWarning, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
#define logTraceError(...) Logger::log(Logger::LogError, fw::mkstr(__VA_ARGS__), __PRETTY_FUNCTION__)
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -197,7 +197,7 @@ R unsafe_cast(const T& t, R def = R()) {
 | 
			
		|||
    try {
 | 
			
		||||
        return safe_cast<R,T>(t);
 | 
			
		||||
    } catch(bad_cast& e) {
 | 
			
		||||
        println(e.what());
 | 
			
		||||
        println("CAST ERROR: ", e.what());
 | 
			
		||||
        return def;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -212,6 +212,21 @@ T fromstring(const std::string& str, T def = T()) {
 | 
			
		|||
    return unsafe_cast<T, std::string>(str, def);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline std::string dec2hex(unsigned int num) {
 | 
			
		||||
    std::string str;
 | 
			
		||||
    std::ostringstream o;
 | 
			
		||||
    o << std::hex << num;
 | 
			
		||||
    str = o.str();
 | 
			
		||||
    return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline unsigned int hex2dec(const std::string& str) {
 | 
			
		||||
    unsigned int num;
 | 
			
		||||
    std::istringstream i(str);
 | 
			
		||||
    i >> std::hex >> num;
 | 
			
		||||
    return num;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// an empty string to use anywhere needed
 | 
			
		||||
const static std::string empty_string;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,8 +60,15 @@ void Creature::draw(int x, int y)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    Rect healthRect = Rect(x - 14, y - 11, 27, 4);
 | 
			
		||||
    g_graphics.drawBoundingRect(healthRect, Color::black);
 | 
			
		||||
    g_graphics.drawFilledRect(healthRect.expanded(-1), healthColor);
 | 
			
		||||
 | 
			
		||||
    g_graphics.bindColor(Color::black);
 | 
			
		||||
    g_graphics.drawBoundingRect(healthRect);
 | 
			
		||||
 | 
			
		||||
    g_graphics.bindColor(healthColor);
 | 
			
		||||
    g_graphics.drawFilledRect(healthRect.expanded(-1));
 | 
			
		||||
 | 
			
		||||
    // restore white color
 | 
			
		||||
    g_graphics.bindColor(Color::white);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const ThingAttributes& Creature::getAttributes()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,7 @@ bool DatManager::load(const std::string& file)
 | 
			
		|||
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError("ERROR: failed to load dat from '", file, "': ", e.what());
 | 
			
		||||
        logError("failed to load dat from '", file, "': ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -48,9 +48,12 @@ void Map::draw(int x, int y)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    // debug draws
 | 
			
		||||
    g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32), Color::red);
 | 
			
		||||
    g_graphics.bindColor(Color::red);
 | 
			
		||||
    g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32));
 | 
			
		||||
 | 
			
		||||
    m_framebuffer->unbind();
 | 
			
		||||
 | 
			
		||||
    g_graphics.bindColor(Color::white);
 | 
			
		||||
    m_framebuffer->draw(Rect(x, y, g_graphics.getScreenSize()));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,16 +10,16 @@ SpriteManager::SpriteManager()
 | 
			
		|||
    m_signature = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool SpriteManager::load(const std::string &filename)
 | 
			
		||||
bool SpriteManager::load(const std::string& file)
 | 
			
		||||
{
 | 
			
		||||
    try {
 | 
			
		||||
        g_resources.loadFile(filename, m_fin);
 | 
			
		||||
        g_resources.loadFile(file, m_fin);
 | 
			
		||||
        m_signature = fw::getu32(m_fin);
 | 
			
		||||
        m_spritesCount = fw::getu16(m_fin);
 | 
			
		||||
        m_sprites.resize(m_spritesCount);
 | 
			
		||||
        return true;
 | 
			
		||||
    } catch(std::exception& e) {
 | 
			
		||||
        logError(e.what());
 | 
			
		||||
        logError("faile to load sprites from '", file, "': ", e.what());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ class SpriteManager
 | 
			
		|||
public:
 | 
			
		||||
    SpriteManager();
 | 
			
		||||
 | 
			
		||||
    bool load(const std::string& filename);
 | 
			
		||||
    bool load(const std::string& file);
 | 
			
		||||
    void unload();
 | 
			
		||||
 | 
			
		||||
    uint32 getSignature() { return m_signature; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -92,7 +92,7 @@ void OTClient::run()
 | 
			
		|||
    m_running = true;
 | 
			
		||||
 | 
			
		||||
    if(g_ui.getRootWidget()->getChildCount() == 0) {
 | 
			
		||||
        logError("ERROR: there is no root widgets to display, the app will close");
 | 
			
		||||
        logError("there is no root widgets to display, the app will close");
 | 
			
		||||
        m_stopping = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -251,7 +251,7 @@ void OTClient::saveConfigurations()
 | 
			
		|||
 | 
			
		||||
    // saves user configuration
 | 
			
		||||
    if(!g_configs.save())
 | 
			
		||||
        logError("ERROR: configurations are lost because it couldn't be saved");
 | 
			
		||||
        logError("configurations are lost because it couldn't be saved");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void OTClient::onClose()
 | 
			
		||||
| 
						 | 
				
			
			@ -270,28 +270,43 @@ void OTClient::onResize(const Size& size)
 | 
			
		|||
 | 
			
		||||
void OTClient::onPlatformEvent(const PlatformEvent& event)
 | 
			
		||||
{
 | 
			
		||||
    g_ui.inputEvent(event);
 | 
			
		||||
    bool fireUi = true;
 | 
			
		||||
 | 
			
		||||
    if(event.type == EventKeyDown) {
 | 
			
		||||
        if(!event.ctrl) {
 | 
			
		||||
        if(!event.ctrl && !event.alt && !event.shift) {
 | 
			
		||||
            if(event.keycode == KC_UP)
 | 
			
		||||
                g_game.walk(DIRECTION_NORTH);
 | 
			
		||||
            if(event.keycode == KC_RIGHT)
 | 
			
		||||
            else if(event.keycode == KC_RIGHT)
 | 
			
		||||
                g_game.walk(DIRECTION_EAST);
 | 
			
		||||
            if(event.keycode == KC_DOWN)
 | 
			
		||||
            else if(event.keycode == KC_DOWN)
 | 
			
		||||
                g_game.walk(DIRECTION_SOUTH);
 | 
			
		||||
            if(event.keycode == KC_LEFT)
 | 
			
		||||
            else if(event.keycode == KC_LEFT)
 | 
			
		||||
                g_game.walk(DIRECTION_WEST);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
        else if(event.ctrl && !event.alt && !event.shift) {
 | 
			
		||||
            if(event.keycode == KC_UP)
 | 
			
		||||
                g_game.turn(DIRECTION_NORTH);
 | 
			
		||||
            if(event.keycode == KC_RIGHT)
 | 
			
		||||
            else if(event.keycode == KC_RIGHT)
 | 
			
		||||
                g_game.turn(DIRECTION_EAST);
 | 
			
		||||
            if(event.keycode == KC_DOWN)
 | 
			
		||||
            else if(event.keycode == KC_DOWN)
 | 
			
		||||
                g_game.turn(DIRECTION_SOUTH);
 | 
			
		||||
            if(event.keycode == KC_LEFT)
 | 
			
		||||
            else if(event.keycode == KC_LEFT)
 | 
			
		||||
                g_game.turn(DIRECTION_WEST);
 | 
			
		||||
            else if(event.keycode == KC_APOSTROPHE) {
 | 
			
		||||
                // TODO: move these events to lua
 | 
			
		||||
                UIWidgetPtr console = g_ui.getRootWidget()->getChildById("consolePanel");
 | 
			
		||||
                if(!console->isVisible()) {
 | 
			
		||||
                    g_ui.getRootWidget()->lockChild(console);
 | 
			
		||||
                    console->setVisible(true);
 | 
			
		||||
                } else {
 | 
			
		||||
                    g_ui.getRootWidget()->unlockChild(console);
 | 
			
		||||
                    console->setVisible(false);
 | 
			
		||||
                }
 | 
			
		||||
                fireUi = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(fireUi)
 | 
			
		||||
        g_ui.inputEvent(event);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
#ifndef OTCLIENT_H
 | 
			
		||||
#define OTCLIENT_H
 | 
			
		||||
 | 
			
		||||
#include <framework/ui/declarations.h>
 | 
			
		||||
#include <framework/platform/platformlistener.h>
 | 
			
		||||
 | 
			
		||||
class OTClient : public PlatformListener
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue