lua console and some changes

This commit is contained in:
Eduardo Bart 2011-08-20 17:30:41 -03:00
parent 033f14780d
commit 38529ea837
70 changed files with 672 additions and 305 deletions

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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;
} }
} }

View File

@ -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; }

View File

@ -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));
}
}

View File

@ -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

View File

@ -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;
} }
} }

View File

@ -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;

View File

@ -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()

View File

@ -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;

View File

@ -18,8 +18,11 @@ 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")) {
calculateGlyphsWidthsAutomatically(glyphSize); for(int glyph = m_firstGlyph; glyph < 256; ++glyph)
m_glyphsSize[glyph] = Size(node->value<int>(), m_glyphHeight);
} else
calculateGlyphsWidthsAutomatically(glyphSize);
// read custom widths // read custom widths
if(OTMLNodePtr node = fontNode->get("glyph widths")) { if(OTMLNodePtr node = fontNode->get("glyph widths")) {

View File

@ -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;
} }

View File

@ -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)

View File

@ -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; }

View File

@ -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;

View File

@ -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());
} }
} }

View File

@ -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));

View File

@ -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;

View File

@ -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);

View File

@ -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,12 +63,28 @@ 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);
// the first argument is always this object (self) if(!g_lua.isNil()) {
g_lua.insert(-2); // the first argument is always this object (self)
g_lua.polymorphicPush(args...); g_lua.insert(-2);
return g_lua.protectedCall(1 + sizeof...(args)); g_lua.polymorphicPush(args...);
return g_lua.protectedCall(1 + sizeof...(args));
} else {
g_lua.pop(2);
}
}
return 0;
}
template<typename R, typename... T>
R LuaObject::callLuaField(const std::string& field, const T&... args) {
R result;
int rets = callLuaField(field, args...);
if(rets > 0) {
assert(rets == 1);
result = g_lua.polymorphicPop<R>();
} else } else
return 0; result = R();
return result;
} }
template<typename T> template<typename T>

View File

@ -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)
{ {

View File

@ -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();
}; };

View File

@ -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;
} }

View File

@ -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

View File

@ -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,

View File

@ -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.keycode = x11.keyMap[keysym];
inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp;
inputEvent.keychar = (len > 0) ? buf[0] : 0; inputEvent.keychar = (len > 0) ? buf[0] : 0;
if(x11.keyMap.find(keysym) != x11.keyMap.end())
inputEvent.keycode = x11.keyMap[keysym];
else
inputEvent.keycode = KC_UNKNOWN;
inputEvent.keycode = x11.keyMap[keysym];
inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp;
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();
} }

View File

@ -9,7 +9,8 @@ enum UIWidgetType {
UITypeButton, UITypeButton,
UITypeLineEdit, UITypeLineEdit,
UITypeWindow, UITypeWindow,
UITypeList UITypeList,
UITypeConsole
}; };
enum FocusReason { enum FocusReason {

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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;
}; };

View File

@ -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));
} }

View File

@ -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

View File

@ -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;

View File

@ -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;
} }
} }

View File

@ -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,21 +629,21 @@ 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;
if(m_lockedWidgets.size() > 0)
newLockedWidget = m_lockedWidgets.front();
for(const UIWidgetPtr& child : m_children) { UIWidgetPtr newLockedWidget;
if(newLockedWidget) { if(m_lockedWidgets.size() > 0)
if(child == newLockedWidget) newLockedWidget = m_lockedWidgets.front();
child->setEnabled(true);
else for(const UIWidgetPtr& child : m_children) {
child->setEnabled(false); if(newLockedWidget) {
} else if(child == newLockedWidget)
child->setEnabled(true); child->setEnabled(true);
} else
child->setEnabled(false);
} else
child->setEnabled(true);
} }
} }

View File

@ -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;

View File

@ -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

View File

@ -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;
} }

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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()

View File

@ -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;
} }
} }

View File

@ -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()));
} }

View File

@ -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;
} }
} }

View File

@ -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; }

View File

@ -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);
} }

View File

@ -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