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