diff --git a/CMakeLists.txt b/CMakeLists.txt index 53c57ab6..b2ef94c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -84,11 +84,11 @@ SET(SOURCES src/framework/net/rsa.cpp # framework util - src/framework/util/logger.cpp src/framework/util/color.cpp src/framework/util/translator.cpp # framework core + src/framework/core/logger.cpp src/framework/core/configs.cpp src/framework/core/resourcemanager.cpp src/framework/core/eventdispatcher.cpp diff --git a/modules/console/console.lua b/modules/console/console.lua new file mode 100644 index 00000000..5246cc41 --- /dev/null +++ b/modules/console/console.lua @@ -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 \ No newline at end of file diff --git a/modules/console/console.otmod b/modules/console/console.otmod new file mode 100644 index 00000000..d0eaff52 --- /dev/null +++ b/modules/console/console.otmod @@ -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() \ No newline at end of file diff --git a/modules/console/console.otui b/modules/console/console.otui new file mode 100644 index 00000000..ca57455e --- /dev/null +++ b/modules/console/console.otui @@ -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 \ No newline at end of file diff --git a/modules/core/constants.lua b/modules/core/constants.lua index 72d6b395..c79df321 100644 --- a/modules/core/constants.lua +++ b/modules/core/constants.lua @@ -6,3 +6,11 @@ AnchorLeft = 3 AnchorRight = 4 AnchorVerticalCenter = 5 AnchorHorizontalCenter = 6 + +LogDebug = 0 +LogInfo = 1 +LogWarning = 2 +LogError = 3 +LogFatal = 4 + +EmptyFunction = function() end \ No newline at end of file diff --git a/modules/core/messagebox.lua b/modules/core/messagebox.lua index 8945cf3c..80e9d3c6 100644 --- a/modules/core/messagebox.lua +++ b/modules/core/messagebox.lua @@ -11,45 +11,48 @@ function MessageBox.create(title, text, flags) -- create messagebox window local window = UIWindow.create() - window.id = "messageBoxWindow" - window.title = title + window:setStyle('Window') + window:setId("messageBoxWindow") + window:setTitle(title) window:centerIn("parent") rootWidget:addChild(window) - window:lock() + rootWidget:lockChild(window) -- create messagebox label local label = UILabel.create() - label.id = "messageBoxLabel" - label.text = text - label:addAnchor(AnchorHorizontalCenter, window.id, AnchorHorizontalCenter) - label:addAnchor(AnchorTop, window.id, AnchorTop) + label:setStyle('Label') + label:setId("messageBoxLabel") + label:setText(text) + label:addAnchor(AnchorHorizontalCenter, window:getId(), AnchorHorizontalCenter) + label:addAnchor(AnchorTop, window:getId(), AnchorTop) label:setMargin(27, 0) label:resizeToText() window:addChild(label) -- set window size based on label size - window.width = label.width + 60 - window.height = label.height + 64 + window:setWidth(label:getWidth() + 60) + window:setHeight(label:getHeight() + 64) -- setup messagebox first button local button1 = UIButton.create() - button1.id = "messageBoxButton1" - button1:addAnchor(AnchorBottom, window.id, AnchorBottom) - button1:addAnchor(AnchorRight, window.id, AnchorRight) + button1:setStyle('Button') + button1:setId("messageBoxButton1") + button1:addAnchor(AnchorBottom, window:getId(), AnchorBottom) + button1:addAnchor(AnchorRight, window:getId(), AnchorRight) button1:setMargin(10) - button1.width = 64 + button1:setWidth(64) window:addChild(button1) if flags == MessageBoxOk then - button1.text = "Ok" - box.onOk = createEmptyFunction() + button1:setText("Ok") + box.onOk = EmptyFunction button1.onClick = function() box.onOk() box:destroy() end elseif flags == MessageBoxCancel then - button1.text = "Cancel" - box.onCancel = createEmptyFunction() + button1:setText("Cancel") + box.onCancel = EmptyFunction button1.onClick = function() box.onCancel() box:destroy() diff --git a/modules/core/util.lua b/modules/core/util.lua index 7e9c6c4f..394c7bdc 100644 --- a/modules/core/util.lua +++ b/modules/core/util.lua @@ -1,5 +1,7 @@ -function createEmptyFunction() - local emptyFunction = function() end - return emptyFunction -end - +function print(...) + local msg = "" + for i,v in ipairs(arg) do + msg = msg .. tostring(v) .. "\t" + end + Logger.log(LogInfo, msg) +end \ No newline at end of file diff --git a/modules/core/widget.lua b/modules/core/widget.lua index afdebbac..edcc0b09 100644 --- a/modules/core/widget.lua +++ b/modules/core/widget.lua @@ -1,19 +1,19 @@ function UIWidget:setMargin(...) local params = {...} if #params == 1 then - self.marginTop = params[1] - self.marginRight = params[1] - self.marginBottom = params[1] - self.marginLeft = params[1] + self:setMarginTop(params[1]) + self:setMarginRight(params[1]) + self:setMarginBottom(params[1]) + self:setMarginLeft(params[1]) elseif #params == 2 then - self.marginTop = params[1] - self.marginRight = params[2] - self.marginBottom = params[1] - self.marginLeft = params[2] + self:setMarginTop(params[1]) + self:setMarginRight(params[2]) + self:setMarginBottom(params[1]) + self:setMarginLeft(params[2]) elseif #params == 4 then - self.marginTop = params[1] - self.marginRight = params[2] - self.marginBottom = params[3] - self.marginLeft = params[4] + self:setMarginTop(params[1]) + self:setMarginRight(params[2]) + self:setMarginBottom(params[3]) + self:setMarginLeft(params[4]) end end \ No newline at end of file diff --git a/modules/core_fonts/core_fonts.otmod b/modules/core_fonts/core_fonts.otmod index eac5071f..e3a401a7 100644 --- a/modules/core_fonts/core_fonts.otmod +++ b/modules/core_fonts/core_fonts.otmod @@ -11,6 +11,7 @@ Module importFont('helvetica-12px-bold') importFont('helvetica-12px') importFont('helvetica-14px-bold') + importFont('terminus-14px-bold') setDefaultFont('helvetica-12px') return true diff --git a/modules/core_fonts/terminus-14px-bold.otfont b/modules/core_fonts/terminus-14px-bold.otfont new file mode 100644 index 00000000..01107b8a --- /dev/null +++ b/modules/core_fonts/terminus-14px-bold.otfont @@ -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 + diff --git a/modules/core_fonts/terminus-14px-bold.png b/modules/core_fonts/terminus-14px-bold.png new file mode 100644 index 00000000..e55e08ec Binary files /dev/null and b/modules/core_fonts/terminus-14px-bold.png differ diff --git a/modules/core_ui/buttons.otui b/modules/core_ui/buttons.otui index 5340072c..9786d933 100644 --- a/modules/core_ui/buttons.otui +++ b/modules/core_ui/buttons.otui @@ -1,6 +1,6 @@ Button < UIButton font: helvetica-11px-bold - font-color: #f0ad4dff + color: #f0ad4dff size: 106 24 border-image: source: /core_ui/images/button.png diff --git a/modules/core_ui/images/empty_rect.png b/modules/core_ui/images/empty_rect.png new file mode 100644 index 00000000..3c087667 Binary files /dev/null and b/modules/core_ui/images/empty_rect.png differ diff --git a/modules/core_ui/labels.otui b/modules/core_ui/labels.otui index 9444c45a..f47653a6 100644 --- a/modules/core_ui/labels.otui +++ b/modules/core_ui/labels.otui @@ -1,5 +1,8 @@ Label < UILabel + font: helvetica-12px + color: #ffffff LargerLabel < Label font: helvetica-12px-bold + color: #ffffff diff --git a/modules/core_ui/lineedits.otui b/modules/core_ui/lineedits.otui index e3caa9b3..4c484b2b 100644 --- a/modules/core_ui/lineedits.otui +++ b/modules/core_ui/lineedits.otui @@ -1,4 +1,5 @@ LineEdit < UILineEdit + font: helvetica-12px size: 86 20 text-margin: 3 border-image: diff --git a/modules/core_ui/panels.otui b/modules/core_ui/panels.otui index 8de46eea..bb94e92a 100644 --- a/modules/core_ui/panels.otui +++ b/modules/core_ui/panels.otui @@ -12,4 +12,4 @@ RoundedPanel < Panel border: 4 RectPanel < UIWidget - image: /core_ui/images/emptyrect.png \ No newline at end of file + image: /core_ui/images/empty_rect.png \ No newline at end of file diff --git a/modules/core_ui/windows.otui b/modules/core_ui/windows.otui index 1b671237..f1c39f64 100644 --- a/modules/core_ui/windows.otui +++ b/modules/core_ui/windows.otui @@ -1,4 +1,5 @@ Window < UIWindow + font: helvetica-12px-bold size: 200 200 head: height: 20 @@ -17,5 +18,4 @@ Window < UIWindow border.top: 0 MainWindow < Window - anchors.centerIn: parent - onLoad: function(self) self:lock() end \ No newline at end of file + anchors.centerIn: parent \ No newline at end of file diff --git a/modules/gfx/gfx.lua b/modules/gfx/gfx.lua index 0cb3efaa..af0aa0db 100644 --- a/modules/gfx/gfx.lua +++ b/modules/gfx/gfx.lua @@ -3,7 +3,7 @@ GFX = { } function GFX.fadeIn(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end - widget.opacity = math.min((255*elapsed)/time, 255) + widget:setOpacity(math.min((255*elapsed)/time, 255)) if elapsed < time then scheduleEvent(function() GFX.fadeIn(widget, time, elapsed + 30) @@ -14,7 +14,7 @@ end function GFX.fadeOut(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end - widget.opacity = (255*(time - elapsed))/time + widget:setOpacity((255*(time - elapsed))/time) if elapsed < time then scheduleEvent(function() GFX.fadeOut(widget, time, elapsed + 30) diff --git a/modules/mainmenu/entergame.lua b/modules/mainmenu/entergame.lua index 4b63f105..3f7d72bc 100644 --- a/modules/mainmenu/entergame.lua +++ b/modules/mainmenu/entergame.lua @@ -31,8 +31,8 @@ function EnterGame_connectToLoginServer() end local enterGameWindow = rootWidget:getChild("enterGameWindow") - local account = enterGameWindow:getChild("accountNameLineEdit").text - local password = enterGameWindow:getChild("accountPasswordLineEdit").text + local account = enterGameWindow:getChild("accountNameLineEdit"):getText() + local password = enterGameWindow:getChild("accountPasswordLineEdit"):getText() protocolLogin:login(account, password) enterGameWindow:destroy() diff --git a/modules/mainmenu/ui/entergamewindow.otui b/modules/mainmenu/ui/entergamewindow.otui index b7d0c6f4..85031f5f 100644 --- a/modules/mainmenu/ui/entergamewindow.otui +++ b/modules/mainmenu/ui/entergamewindow.otui @@ -50,4 +50,4 @@ MainWindow anchors.bottom: parent.bottom margin.bottom: 16 margin.right: 16 - onClick: function(self) GFX.fadeOut(self.parent) end + onClick: function(self) GFX.fadeOut(self:getParent()) end diff --git a/modules/mainmenu/ui/infowindow.otui b/modules/mainmenu/ui/infowindow.otui index 4a982462..bd48f73a 100644 --- a/modules/mainmenu/ui/infowindow.otui +++ b/modules/mainmenu/ui/infowindow.otui @@ -58,4 +58,4 @@ MainWindow anchors.top: parent.top margin.top: 191 margin.left: 188 - onClick: function(self) self.parent:destroy() end + onClick: function(self) self:getParent():destroy() end diff --git a/modules/mainmenu/ui/optionswindow.otui b/modules/mainmenu/ui/optionswindow.otui index d87451df..c2130410 100644 --- a/modules/mainmenu/ui/optionswindow.otui +++ b/modules/mainmenu/ui/optionswindow.otui @@ -113,4 +113,4 @@ MainWindow anchors.bottom: parent.bottom margin.right: 10 margin.bottom: 13 - onClick: function(self) self.parent:destroy() end + onClick: function(self) self:getParent():destroy() end diff --git a/src/framework/const.h b/src/framework/const.h index f3abb3d7..da642335 100644 --- a/src/framework/const.h +++ b/src/framework/const.h @@ -3,6 +3,14 @@ //namespace fw { +enum LogLevel { + LogDebug = 0, + LogInfo, + LogWarning, + LogError, + LogFatal +}; + enum AlignmentFlag { AlignLeft = 1, AlignRight = 2, diff --git a/src/framework/core/configs.cpp b/src/framework/core/configs.cpp index 2662e810..379fda00 100644 --- a/src/framework/core/configs.cpp +++ b/src/framework/core/configs.cpp @@ -5,17 +5,20 @@ Configs g_configs; -bool Configs::load(const std::string& fileName) +bool Configs::load(const std::string& file) { - m_fileName = fileName; + m_fileName = file; + + if(!g_resources.fileExists(file)) + return false; try { - OTMLDocumentPtr doc = OTMLDocument::parse(fileName); + OTMLDocumentPtr doc = OTMLDocument::parse(file); for(const OTMLNodePtr& child : doc->children()) m_confsMap[child->tag()] = child->value(); return true; } catch(std::exception& e) { - logError("ERROR: could not load configurations: ", e.what()); + logError("could not load configurations: ", e.what()); return false; } } diff --git a/src/framework/core/configs.h b/src/framework/core/configs.h index 097741f3..39e8ae97 100644 --- a/src/framework/core/configs.h +++ b/src/framework/core/configs.h @@ -6,7 +6,7 @@ class Configs { public: - bool load(const std::string& fileName); + bool load(const std::string& file); bool save(); void set(const std::string& key, const std::string& value) { m_confsMap[key] = value; } diff --git a/src/framework/core/logger.cpp b/src/framework/core/logger.cpp new file mode 100644 index 00000000..adf611ad --- /dev/null +++ b/src/framework/core/logger.cpp @@ -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)); + } +} diff --git a/src/framework/core/logger.h b/src/framework/core/logger.h new file mode 100644 index 00000000..fb229cf7 --- /dev/null +++ b/src/framework/core/logger.h @@ -0,0 +1,49 @@ +#ifndef LOGGER_H +#define LOGGER_H + +#include "../util/tools.h" +#include +#include + +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 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 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 \ No newline at end of file diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index f85d661b..e01460f5 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -54,7 +54,7 @@ bool Module::load() logInfo("Loaded module '", m_name, "'"); return true; } catch(std::exception& e) { - logError("ERROR: failed to load module '", m_name, "': ", e.what()); + logError("failed to load module '", m_name, "': ", e.what()); return false; } } diff --git a/src/framework/core/modulemanager.cpp b/src/framework/core/modulemanager.cpp index 6b8388e6..b0e8785a 100644 --- a/src/framework/core/modulemanager.cpp +++ b/src/framework/core/modulemanager.cpp @@ -38,7 +38,7 @@ bool ModuleManager::discoverModule(const std::string& file) module->discover(moduleNode); m_modules.push_back(module); } catch(std::exception& e) { - logError("ERROR: failed to load module from '", file, "': ", e.what()); + logError("failed to load module from '", file, "': ", e.what()); return false; } return true; diff --git a/src/framework/core/resourcemanager.cpp b/src/framework/core/resourcemanager.cpp index cfe1f6ef..5e81a5d6 100644 --- a/src/framework/core/resourcemanager.cpp +++ b/src/framework/core/resourcemanager.cpp @@ -30,14 +30,14 @@ void ResourceManager::init(const char* argv0) } if(!found) - logFatal("FATAL ERROR: could not find modules directory"); + logFatal("could not find modules directory"); // setup write directory std::string dir = g_platform.getAppUserDir(); if(g_resources.setWriteDir(dir)) g_resources.addToSearchPath(dir); else - logError("ERROR: could not setup write directory"); + logError("could not setup write directory"); } void ResourceManager::terminate() diff --git a/src/framework/global.h b/src/framework/global.h index 252c35db..0005d443 100644 --- a/src/framework/global.h +++ b/src/framework/global.h @@ -41,13 +41,15 @@ // additional utilities #include "util/types.h" #include "util/tools.h" -#include "util/logger.h" #include "util/translator.h" #include "util/point.h" #include "util/color.h" #include "util/rect.h" #include "util/size.h" +// logger +#include "core/logger.h" + // easy typing for _1, _2, ... using namespace std::placeholders; diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp index 417f4403..e4d52d9c 100644 --- a/src/framework/graphics/font.cpp +++ b/src/framework/graphics/font.cpp @@ -18,8 +18,11 @@ void Font::load(const OTMLNodePtr& fontNode) if(!m_texture) throw std::runtime_error("failed to load texture for font"); - // auto calculate widths - calculateGlyphsWidthsAutomatically(glyphSize); + if(OTMLNodePtr node = fontNode->get("fixed glyph width")) { + for(int glyph = m_firstGlyph; glyph < 256; ++glyph) + m_glyphsSize[glyph] = Size(node->value(), m_glyphHeight); + } else + calculateGlyphsWidthsAutomatically(glyphSize); // read custom widths if(OTMLNodePtr node = fontNode->get("glyph widths")) { diff --git a/src/framework/graphics/fontmanager.cpp b/src/framework/graphics/fontmanager.cpp index 5179c5be..ce04f89e 100644 --- a/src/framework/graphics/fontmanager.cpp +++ b/src/framework/graphics/fontmanager.cpp @@ -34,7 +34,7 @@ bool FontManager::importFont(std::string fontFile) return true; } catch(std::exception& e) { - logError("ERROR: could not load font from '", fontFile, "': ", e.what()); + logError("could not load font from '", fontFile, "': ", e.what()); return false; } } @@ -64,6 +64,6 @@ FontPtr FontManager::getDefaultFont() { // default font should always exists, otherwise the app may crash if(!m_defaultFont) - logFatal("FATAL ERROR: no default font to display, cannot continue to run"); + logFatal("no default font to display, cannot continue to run"); return m_defaultFont; } diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 531d2074..d1627ed0 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -194,8 +194,7 @@ void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, stopDrawing(); } -void Graphics::drawFilledRect(const Rect& screenCoords, - const Color& color) +void Graphics::drawFilledRect(const Rect& screenCoords) { assert(!m_drawing); @@ -208,8 +207,6 @@ void Graphics::drawFilledRect(const Rect& screenCoords, int top = screenCoords.top(); int left = screenCoords.left(); - glPushAttrib(GL_CURRENT_BIT); - glColor4ubv(color.rgbaPtr()); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); @@ -220,12 +217,10 @@ void Graphics::drawFilledRect(const Rect& screenCoords, glEnd(); glEnable(GL_TEXTURE_2D); - glPopAttrib(); } void Graphics::drawBoundingRect(const Rect& screenCoords, - const Color& color, int innerLineWidth) { assert(!m_drawing); @@ -239,8 +234,6 @@ void Graphics::drawBoundingRect(const Rect& screenCoords, int top = screenCoords.top(); int left = screenCoords.left(); - glPushAttrib(GL_CURRENT_BIT); - glColor4ubv(color.rgbaPtr()); glDisable(GL_TEXTURE_2D); glBegin(GL_QUADS); @@ -270,7 +263,6 @@ void Graphics::drawBoundingRect(const Rect& screenCoords, glEnd(); glEnable(GL_TEXTURE_2D); - glPopAttrib(); } void Graphics::bindColor(const Color& color) diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index 0719d692..4dca7d2c 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -45,11 +45,9 @@ public: const TexturePtr& texture, const Rect& textureCoords); - void drawFilledRect(const Rect& screenCoords, - const Color& color); + void drawFilledRect(const Rect& screenCoords); void drawBoundingRect(const Rect& screenCoords, - const Color& color = Color::green, int innerLineWidth = 1); const Size& getScreenSize() const { return m_screenSize; } diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index 9dc929f4..9979d8e8 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -35,7 +35,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int // checks texture max size if(width > maxTexSize || height > maxTexSize) { - logError("ERROR: loading texture with size ", width, "x", height, " failed, " + logError("loading texture with size ", width, "x", height, " failed, " "the maximum size allowed by the graphics card is ", maxTexSize, "x", maxTexSize, ",", "to prevent crashes the texture will be displayed as a blank texture"); return 0; diff --git a/src/framework/graphics/texturemanager.cpp b/src/framework/graphics/texturemanager.cpp index 2ddc063c..3e90f490 100644 --- a/src/framework/graphics/texturemanager.cpp +++ b/src/framework/graphics/texturemanager.cpp @@ -31,7 +31,7 @@ TexturePtr TextureManager::getTexture(const std::string& textureFile) g_resources.loadFile(textureFile, fin); texture = loadPNG(fin); } catch(std::exception& e) { - logError("ERROR: unable to load texture '",textureFile,"': ", e.what()); + logError("unable to load texture '",textureFile,"': ", e.what()); } } diff --git a/src/framework/luascript/luafunctions.cpp b/src/framework/luascript/luafunctions.cpp index 3c935742..7accc5eb 100644 --- a/src/framework/luascript/luafunctions.cpp +++ b/src/framework/luascript/luafunctions.cpp @@ -10,51 +10,71 @@ void LuaInterface::registerFunctions() // UIWidget g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); - - g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); - g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); - - g_lua.bindClassMemberField("id", &UIWidget::getId, &UIWidget::setId); - g_lua.bindClassMemberField("enabled", &UIWidget::isEnabled, &UIWidget::setEnabled); - g_lua.bindClassMemberField("visible", &UIWidget::isVisible, &UIWidget::setVisible); - g_lua.bindClassMemberField("width", &UIWidget::getWidth, &UIWidget::setWidth); - g_lua.bindClassMemberField("height", &UIWidget::getHeight, &UIWidget::setHeight); - g_lua.bindClassMemberField("parent", &UIWidget::getParent, &UIWidget::setParent); - g_lua.bindClassMemberField("color", &UIWidget::getColor, &UIWidget::setColor); - g_lua.bindClassMemberField("opacity", &UIWidget::getOpacity, &UIWidget::setOpacity); - g_lua.bindClassMemberField("marginTop", &UIWidget::getMarginTop, &UIWidget::setMarginTop); - g_lua.bindClassMemberField("marginBottom", &UIWidget::getMarginBottom, &UIWidget::setMarginBottom); - g_lua.bindClassMemberField("marginLeft", &UIWidget::getMarginLeft, &UIWidget::setMarginLeft); - g_lua.bindClassMemberField("marginRight", &UIWidget::getMarginRight, &UIWidget::setMarginRight); + g_lua.bindClassMemberFunction("getId", &UIWidget::getId); + g_lua.bindClassMemberFunction("setId", &UIWidget::setId); + g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); + g_lua.bindClassMemberFunction("setEnabled", &UIWidget::setEnabled); + g_lua.bindClassMemberFunction("isVisible", &UIWidget::isVisible); + g_lua.bindClassMemberFunction("setVisible", &UIWidget::setVisible); + g_lua.bindClassMemberFunction("getWidth", &UIWidget::getWidth); + g_lua.bindClassMemberFunction("setWidth", &UIWidget::setWidth); + g_lua.bindClassMemberFunction("getHeight", &UIWidget::getHeight); + g_lua.bindClassMemberFunction("setHeight", &UIWidget::setHeight); + g_lua.bindClassMemberFunction("getParent", &UIWidget::getParent); + g_lua.bindClassMemberFunction("setParent", &UIWidget::setParent); + g_lua.bindClassMemberFunction("getBackgroundColor", &UIWidget::getBackgroundColor); + g_lua.bindClassMemberFunction("setBackgroundColor", &UIWidget::setBackgroundColor); + g_lua.bindClassMemberFunction("getForegroundColor", &UIWidget::getForegroundColor); + g_lua.bindClassMemberFunction("setForegroundColor", &UIWidget::setForegroundColor); + g_lua.bindClassMemberFunction("getOpacity", &UIWidget::getOpacity); + g_lua.bindClassMemberFunction("setOpacity", &UIWidget::setOpacity); + g_lua.bindClassMemberFunction("setStyle", &UIWidget::setStyle); + g_lua.bindClassMemberFunction("getMarginTop", &UIWidget::getMarginTop); + g_lua.bindClassMemberFunction("setMarginTop", &UIWidget::setMarginTop); + g_lua.bindClassMemberFunction("getMarginBottom", &UIWidget::getMarginBottom); + g_lua.bindClassMemberFunction("setMarginBottom", &UIWidget::setMarginBottom); + g_lua.bindClassMemberFunction("getMarginLeft", &UIWidget::getMarginLeft); + g_lua.bindClassMemberFunction("setMarginLeft", &UIWidget::setMarginLeft); + g_lua.bindClassMemberFunction("getMarginRight", &UIWidget::getMarginRight); + g_lua.bindClassMemberFunction("setMarginRight", &UIWidget::setMarginRight); + g_lua.bindClassMemberFunction("hide", &UIWidget::hide); + g_lua.bindClassMemberFunction("show", &UIWidget::show); + g_lua.bindClassMemberFunction("fill", &UIWidget::fill); g_lua.bindClassMemberFunction("centerIn", &UIWidget::centerIn); g_lua.bindClassMemberFunction("addAnchor", &UIWidget::addAnchor); g_lua.bindClassMemberFunction("getChild", &UIWidget::getChildById); + g_lua.bindClassMemberFunction("insertChild", &UIWidget::insertChild); + g_lua.bindClassMemberFunction("removeChild", &UIWidget::removeChild); g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); - g_lua.bindClassMemberFunction("lock", &UIWidget::lock); - g_lua.bindClassMemberFunction("hide", &UIWidget::hide); - g_lua.bindClassMemberFunction("show", &UIWidget::show); + g_lua.bindClassMemberFunction("lockChild", &UIWidget::lockChild); + g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); // UILabel g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UILabel::create); - g_lua.bindClassMemberField("text", &UILabel::getText, &UILabel::setText); + g_lua.bindClassMemberFunction("getText", &UILabel::getText); + g_lua.bindClassMemberFunction("setText", &UILabel::setText); g_lua.bindClassMemberFunction("resizeToText", &UILabel::resizeToText); // UIButton g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIButton::create); - g_lua.bindClassMemberField("text", &UIButton::getText, &UIButton::setText); + g_lua.bindClassMemberFunction("getText", &UIButton::getText); + g_lua.bindClassMemberFunction("setText", &UIButton::setText); // UILineEdit g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UILineEdit::create); - g_lua.bindClassMemberField("text", &UILineEdit::getText, &UILineEdit::setText); + g_lua.bindClassMemberFunction("getText", &UILineEdit::getText); + g_lua.bindClassMemberFunction("setText", &UILineEdit::setText); + g_lua.bindClassMemberFunction("clearText", &UILineEdit::clearText); // UIWindow g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWindow::create); - g_lua.bindClassMemberField("title", &UIWindow::getTitle, &UIWindow::setTitle); + g_lua.bindClassMemberFunction("getTitle", &UIWindow::getTitle); + g_lua.bindClassMemberFunction("setTitle", &UIWindow::setTitle); // Protocol g_lua.registerClass(); @@ -64,6 +84,12 @@ void LuaInterface::registerFunctions() g_lua.bindClassStaticFunction("set", std::bind(&Configs::set, &g_configs, _1, _2)); g_lua.bindClassStaticFunction("get", std::bind(&Configs::get, &g_configs, _1)); + // Logger + g_lua.registerClass(); + g_lua.bindClassStaticFunction("log", std::bind(&Logger::log, &g_logger, _1, _2)); + g_lua.bindClassStaticFunction("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger)); + g_lua.bindClassStaticFunction("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1)); + // global functions g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1)); diff --git a/src/framework/luascript/luainterface.cpp b/src/framework/luascript/luainterface.cpp index d8f149b4..58b5370b 100644 --- a/src/framework/luascript/luainterface.cpp +++ b/src/framework/luascript/luainterface.cpp @@ -422,7 +422,7 @@ int LuaInterface::protectedCall(int numArgs, int requestedResults) throw LuaException("attempt to call a non function value", 0); } } catch(LuaException &e) { - logError(e.what()); + logError("protected lua call failed: ", e.what()); } // pushes nil values if needed @@ -457,7 +457,7 @@ int LuaInterface::luaScriptLoader(lua_State* L) g_lua.loadScript(fileName); return 1; } catch(LuaException& e) { - logError("ERROR: failed to load script file '", fileName, "' :'", e.what()); + logError("failed to load script file '", fileName, "' :'", e.what()); return 0; } } @@ -489,7 +489,7 @@ int LuaInterface::luaCppFunctionCallback(lua_State* L) numRets = (*(funcPtr->get()))(&g_lua); assert(numRets == g_lua.stackSize()); } catch(LuaException &e) { - logError(e.what()); + logError("lua cpp callback failed: ", e.what()); } return numRets; diff --git a/src/framework/luascript/luaobject.cpp b/src/framework/luascript/luaobject.cpp index 1a5dd3dd..416c0b04 100644 --- a/src/framework/luascript/luaobject.cpp +++ b/src/framework/luascript/luaobject.cpp @@ -7,10 +7,10 @@ LuaObject::LuaObject() : m_fieldsTableRef(-1) LuaObject::~LuaObject() { - luaReleaseFieldsTable(); + releaseLuaFieldsTable(); } -void LuaObject::luaReleaseFieldsTable() +void LuaObject::releaseLuaFieldsTable() { if(m_fieldsTableRef != -1) g_lua.unref(m_fieldsTableRef); diff --git a/src/framework/luascript/luaobject.h b/src/framework/luascript/luaobject.h index 31193928..27fe86f3 100644 --- a/src/framework/luascript/luaobject.h +++ b/src/framework/luascript/luaobject.h @@ -15,6 +15,8 @@ public: /// @return the number of results template int callLuaField(const std::string& field, const T&... args); + template + R callLuaField(const std::string& field, const T&... args); /// Sets a field in this lua object template @@ -25,7 +27,7 @@ public: T getLuaField(const std::string& key); /// Release fields table reference - void luaReleaseFieldsTable(); + void releaseLuaFieldsTable(); /// Sets a field from this lua object, the value must be on the stack void luaSetField(const std::string& key); @@ -61,12 +63,28 @@ int LuaObject::callLuaField(const std::string& field, const T&... args) { g_lua.pushObject(asLuaObject()); g_lua.getField(field); - // the first argument is always this object (self) - g_lua.insert(-2); - g_lua.polymorphicPush(args...); - return g_lua.protectedCall(1 + sizeof...(args)); + if(!g_lua.isNil()) { + // the first argument is always this object (self) + g_lua.insert(-2); + g_lua.polymorphicPush(args...); + return g_lua.protectedCall(1 + sizeof...(args)); + } else { + g_lua.pop(2); + } + } + return 0; +} + +template +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(); } else - return 0; + result = R(); + return result; } template @@ -81,4 +99,4 @@ T LuaObject::getLuaField(const std::string& key) { return g_lua.polymorphicPop(); } -#endif +#endif \ No newline at end of file diff --git a/src/framework/luascript/luavaluecasts.cpp b/src/framework/luascript/luavaluecasts.cpp index 140db9ec..5606fad3 100644 --- a/src/framework/luascript/luavaluecasts.cpp +++ b/src/framework/luascript/luavaluecasts.cpp @@ -42,6 +42,20 @@ bool luavalue_cast(int index, double& d) return true; } +// size_t +void push_luavalue(std::size_t s) +{ + push_luavalue((double)s); +} + +bool luavalue_cast(int index, std::size_t& s) +{ + double d; + bool ret = luavalue_cast(index, d); + s = d; + return ret; +} + // string void push_luavalue(const char* cstr) { diff --git a/src/framework/luascript/luavaluecasts.h b/src/framework/luascript/luavaluecasts.h index 0cbd06d0..f5cfd4d2 100644 --- a/src/framework/luascript/luavaluecasts.h +++ b/src/framework/luascript/luavaluecasts.h @@ -18,6 +18,10 @@ bool luavalue_cast(int index, int& i); void push_luavalue(double d); bool luavalue_cast(int index, double& d); +// size_t +void push_luavalue(std::size_t s); +bool luavalue_cast(int index, std::size_t& s); + // string void push_luavalue(const char* cstr); void push_luavalue(const std::string& str); @@ -131,7 +135,7 @@ bool luavalue_cast(int index, std::function& func) { "did you forget to hold a reference for that function?", 0); } } catch(std::exception& e) { - logError(e.what()); + logError("lua function callback failed: ", e.what()); } }; return true; @@ -165,7 +169,7 @@ luavalue_cast(int index, std::function& func) { "did you forget to hold a reference for that function?", 0); } } catch(std::exception& e) { - logError(e.what()); + logError("lua function callback failed: ", e.what()); } return Ret(); }; diff --git a/src/framework/net/protocol.cpp b/src/framework/net/protocol.cpp index 5963aa2b..2e490b21 100644 --- a/src/framework/net/protocol.cpp +++ b/src/framework/net/protocol.cpp @@ -67,7 +67,7 @@ void Protocol::internalRecvData(uint8* buffer, uint16 size) uint32 checksum = getAdlerChecksum(m_inputMessage.getBuffer() + InputMessage::DATA_POS, m_inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH); if(m_inputMessage.getU32() != checksum) { // error - logError("ERROR: got a network message with invalid checksum"); + logError("got a network message with invalid checksum"); return; } } @@ -93,7 +93,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage) // FIXME: this function has not been tested yet uint16 messageSize = inputMessage.getMessageSize() - InputMessage::CHECKSUM_LENGTH; if(messageSize % 8 != 0) { - logError("ERROR: invalid encrypted network message"); + logError("invalid encrypted network message"); return false; } @@ -116,7 +116,7 @@ bool Protocol::xteaDecrypt(InputMessage& inputMessage) int tmp = inputMessage.getU16(); if(tmp > inputMessage.getMessageSize() - 4) { - logDebug("ERROR: invalid decrypted a network message"); + logError("invalid decrypted a network message"); return false; } diff --git a/src/framework/otml/otmldocument.h b/src/framework/otml/otmldocument.h index bb0d3bff..5a74251e 100644 --- a/src/framework/otml/otmldocument.h +++ b/src/framework/otml/otmldocument.h @@ -6,7 +6,6 @@ class OTMLDocument : public OTMLNode { public: - OTMLDocument() { } virtual ~OTMLDocument() { } /// Create a new OTML document for filling it with nodes @@ -24,6 +23,9 @@ public: /// Save this document to a file bool save(const std::string& fileName); + +private: + OTMLDocument() { } }; #endif diff --git a/src/framework/platform/platformevent.h b/src/framework/platform/platformevent.h index 3016bd5e..9ea83f34 100644 --- a/src/framework/platform/platformevent.h +++ b/src/framework/platform/platformevent.h @@ -161,7 +161,6 @@ enum PlatformEventType { EventMouseLeftButton = 32, EventMouseRightButton = 64, EventMouseMidButton = 128, - EventTextEnter = 256, EventKeyDown = EventKeyboardAction | EventDown, EventKeyUp = EventKeyboardAction | EventUp, EventMouseMove = EventMouseAction | 512, diff --git a/src/framework/platform/x11platform.cpp b/src/framework/platform/x11platform.cpp index ff850932..c035f281 100644 --- a/src/framework/platform/x11platform.cpp +++ b/src/framework/platform/x11platform.cpp @@ -217,17 +217,17 @@ void Platform::init(PlatformListener* platformListener, const char *appName) // open display x11.display = XOpenDisplay(0); if(!x11.display) - logFatal("FATAL ERROR: Failed to open X display"); + logFatal("Failed to open X display"); // check if GLX is supported on this display if(!glXQueryExtension(x11.display, 0, 0)) - logFatal("FATAL ERROR: GLX not supported"); + logFatal("GLX not supported"); // retrieve GLX version int glxMajor; int glxMinor; if(!glXQueryVersion(x11.display, &glxMajor, &glxMinor)) - logFatal("FATAL ERROR: Unable to query GLX version"); + logFatal("Unable to query GLX version"); logInfo("GLX version ",glxMajor,".",glxMinor); // clipboard related atoms @@ -313,6 +313,7 @@ void Platform::poll() inputEvent.ctrl = (event.xkey.state & ControlMask); inputEvent.shift = (event.xkey.state & ShiftMask); inputEvent.alt = (event.xkey.state & Mod1Mask); + inputEvent.keychar = 0; // fire enter text event if(event.type == KeyPress && !inputEvent.ctrl && !inputEvent.alt) { @@ -325,7 +326,7 @@ void Platform::poll() } if(len > 0 && - // for some reason these keys produces characters and we don't want that + // these keys produces characters that we don't want to capture keysym != XK_BackSpace && keysym != XK_Return && keysym != XK_Delete && @@ -333,10 +334,7 @@ void Platform::poll() (uchar)(buf[0]) >= 32 ) { //logDebug("char: ", buf[0], " code: ", (uint)buf[0]); - inputEvent.type = EventTextEnter; inputEvent.keychar = buf[0]; - inputEvent.keycode = KC_UNKNOWN; - m_listener->onPlatformEvent(inputEvent); } } @@ -344,13 +342,19 @@ void Platform::poll() event.xkey.state &= ~(ShiftMask | LockMask); len = XLookupString(&event.xkey, buf, sizeof(buf), &keysym, 0); - // fire key up/down event - if(x11.keyMap.find(keysym) != x11.keyMap.end()) { - inputEvent.keycode = x11.keyMap[keysym]; - inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp; + if(inputEvent.keychar == 0) inputEvent.keychar = (len > 0) ? buf[0] : 0; + + if(x11.keyMap.find(keysym) != x11.keyMap.end()) + inputEvent.keycode = x11.keyMap[keysym]; + else + inputEvent.keycode = KC_UNKNOWN; + + inputEvent.keycode = x11.keyMap[keysym]; + inputEvent.type = (event.type == KeyPress) ? EventKeyDown : EventKeyUp; + + if(inputEvent.keycode != KC_UNKNOWN || inputEvent.keychar != 0) m_listener->onPlatformEvent(inputEvent); - } break; } case ButtonPress: @@ -480,12 +484,12 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i // choose OpenGL, RGBA, double buffered, visual x11.visual = glXChooseVisual(x11.display, DefaultScreen(x11.display), attrList); if(!x11.visual) - logFatal("FATAL ERROR: RGBA/Double buffered visual not supported"); + logFatal("RGBA/Double buffered visual not supported"); // create GLX context x11.glxContext = glXCreateContext(x11.display, x11.visual, 0, GL_TRUE); if(!x11.glxContext) - logFatal("FATAL ERROR: Unable to create GLX context"); + logFatal("Unable to create GLX context"); // color map x11.colormap = XCreateColormap(x11.display, @@ -518,7 +522,7 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i &wa); if(!x11.window) - logFatal("FATAL ERROR: Unable to create X window"); + logFatal("Unable to create X window"); // create input context (to have better key input handling) if(XSupportsLocale()) { @@ -530,11 +534,11 @@ bool Platform::createWindow(int x, int y, int width, int height, int minWidth, i XIMPreeditNothing | XIMStatusNothing, XNClientWindow, x11.window, NULL); if(!x11.xic) - logError("ERROR: Unable to create the input context"); + logError("Unable to create the input context"); } else - logError("ERROR: Failed to open an input method"); + logError("Failed to open an input method"); } else - logError("ERROR: X11 does not support the current locale"); + logError("X11 does not support the current locale"); if(!x11.xic) logWarning("Input of special keys maybe messed up because we couldn't create an input context"); @@ -823,6 +827,6 @@ std::string Platform::getAppUserDir() std::stringstream sdir; sdir << PHYSFS_getUserDir() << "." << x11.appName; if((mkdir(sdir.str().c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0) && (errno != EEXIST)) - logError("ERROR: Couldn't create directory for saving configuration file. (",sdir.str(),")"); + logError("Couldn't create directory for saving configuration file. (",sdir.str(),")"); return sdir.str(); } \ No newline at end of file diff --git a/src/framework/ui/const.h b/src/framework/ui/const.h index aec0cad6..d63e0382 100644 --- a/src/framework/ui/const.h +++ b/src/framework/ui/const.h @@ -9,7 +9,8 @@ enum UIWidgetType { UITypeButton, UITypeLineEdit, UITypeWindow, - UITypeList + UITypeList, + UITypeConsole }; enum FocusReason { diff --git a/src/framework/ui/declarations.h b/src/framework/ui/declarations.h index d5339b44..18dfb745 100644 --- a/src/framework/ui/declarations.h +++ b/src/framework/ui/declarations.h @@ -13,6 +13,7 @@ class UILabel; class UIButton; class UILineEdit; class UIWindow; +class UIConsole; typedef std::shared_ptr UIWidgetPtr; typedef std::weak_ptr UIWidgetWeakPtr; @@ -25,5 +26,6 @@ typedef std::shared_ptr UILabelPtr; typedef std::shared_ptr UIButtonPtr; typedef std::shared_ptr UILineEditPtr; typedef std::shared_ptr UIWindowPtr; +typedef std::shared_ptr UIConsolePtr; #endif diff --git a/src/framework/ui/uianchorlayout.cpp b/src/framework/ui/uianchorlayout.cpp index a3a439be..6bbc2776 100644 --- a/src/framework/ui/uianchorlayout.cpp +++ b/src/framework/ui/uianchorlayout.cpp @@ -8,23 +8,32 @@ bool UIAnchorLayout::addAnchor(const UIWidgetPtr& anchoredWidget, AnchorPoint an /* if(!anchorLineWidget) { - logError("ERROR: could not find the widget to anchor on, wrong id?"); + logError("could not find the widget to anchor on, wrong id?"); return false; } */ // we can never anchor with itself if(anchoredWidget == anchorLineWidget) { - logError("ERROR: anchoring with itself is not possible"); + logError("anchoring with itself is not possible"); return false; } // we must never anchor to an anchor child if(anchoredWidget && hasWidgetInAnchorTree(anchorLineWidget, anchoredWidget)) { - logError("ERROR: anchors is miss configured, you must never make an anchor chains in loops"); + logError("anchors is miss configured, you must never make an anchor chains in loops"); return false; } + // avoid duplicated anchors + for(auto it = m_anchors.begin(); it != m_anchors.end(); ++it) { + const UIAnchor& otherAnchor = *it; + if(otherAnchor.getAnchoredWidget() == anchoredWidget && otherAnchor.getAnchoredEdge() == anchoredEdge) { + m_anchors.erase(it); + break; + } + } + // setup the anchor m_anchors.push_back(anchor); diff --git a/src/framework/ui/uibutton.cpp b/src/framework/ui/uibutton.cpp index 314db6df..fcceafd5 100644 --- a/src/framework/ui/uibutton.cpp +++ b/src/framework/ui/uibutton.cpp @@ -3,6 +3,7 @@ #include #include #include +#include UIButton::UIButton(): UIWidget(UITypeButton) { @@ -25,8 +26,8 @@ void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode) for(int i=0; i<3; ++i) { m_statesStyle[i].image = m_image; - m_statesStyle[i].color = m_color; - m_statesStyle[i].fontColor = m_fontColor; + m_statesStyle[i].color = m_backgroundColor; + m_statesStyle[i].foregroundColor = m_foregroundColor; m_statesStyle[i].textTranslate = Point(0,0); } @@ -40,8 +41,8 @@ void UIButton::loadStyleFromOTML(const OTMLNodePtr& styleNode) m_text = styleNode->valueAt("text", fw::empty_string); if(OTMLNodePtr node = styleNode->get("onClick")) { - g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); - luaSetField("onClick"); + g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + luaSetField(node->tag()); } } @@ -52,20 +53,24 @@ void UIButton::loadStateStyle(ButtonStateStyle& stateStyle, const OTMLNodePtr& s if(OTMLNodePtr node = stateStyleNode->get("image")) stateStyle.image = Image::loadFromOTML(node); stateStyle.textTranslate = stateStyleNode->valueAt("text-translate", Point()); - stateStyle.color = stateStyleNode->valueAt("font-color", m_fontColor); - stateStyle.color = stateStyleNode->valueAt("color", m_color); + stateStyle.color = stateStyleNode->valueAt("font-color", m_foregroundColor); + stateStyle.color = stateStyleNode->valueAt("color", m_backgroundColor); } void UIButton::render() { + UIWidget::render(); + const ButtonStateStyle& currentStyle = m_statesStyle[m_state]; Rect textRect = getGeometry(); - if(currentStyle.image) + if(currentStyle.image) { + g_graphics.bindColor(currentStyle.color); currentStyle.image->draw(textRect); + } textRect.translate(currentStyle.textTranslate); - getFont()->renderText(m_text, textRect, AlignCenter, currentStyle.fontColor); + m_font->renderText(m_text, textRect, AlignCenter, currentStyle.foregroundColor); } void UIButton::onHoverChange(UIHoverEvent& event) diff --git a/src/framework/ui/uibutton.h b/src/framework/ui/uibutton.h index 66572ed8..0639aea2 100644 --- a/src/framework/ui/uibutton.h +++ b/src/framework/ui/uibutton.h @@ -8,7 +8,7 @@ class UIButton : public UIWidget struct ButtonStateStyle { ImagePtr image; Point textTranslate; - Color fontColor; + Color foregroundColor; Color color; }; diff --git a/src/framework/ui/uilabel.cpp b/src/framework/ui/uilabel.cpp index 8813e5fc..c7cd8c09 100644 --- a/src/framework/ui/uilabel.cpp +++ b/src/framework/ui/uilabel.cpp @@ -10,7 +10,6 @@ UILabel::UILabel() : UIWidget(UITypeLabel) UILabelPtr UILabel::create() { UILabelPtr label(new UILabel); - label->setStyle("Label"); return label; } @@ -23,17 +22,23 @@ void UILabel::loadStyleFromOTML(const OTMLNodePtr& styleNode) if(styleNode->hasChildAt("align")) m_align = fw::translateAlignment(styleNode->valueAt("align")); - // auto resize if no size supplied - if(!m_text.empty() && !getGeometry().isValid()) - resizeToText(); + // auto resize if needed + if(!m_text.empty() && !m_rect.isValid()) { + Size textSize = m_font->calculateTextRectSize(m_text); + if(m_rect.width() <= 0) + m_rect.setWidth(textSize.width()); + if(m_rect.height() <= 0) + m_rect.setHeight(textSize.height()); + } } void UILabel::render() { - m_font->renderText(m_text, m_rect, m_align, m_fontColor); + UIWidget::render(); + m_font->renderText(m_text, m_rect, m_align, m_foregroundColor); } void UILabel::resizeToText() { - resize(getFont()->calculateTextRectSize(m_text)); + resize(m_font->calculateTextRectSize(m_text)); } diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 45d9b501..ce21da8e 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -12,6 +12,8 @@ UILineEdit::UILineEdit() : UIWidget(UITypeLabel) m_textHorizontalMargin = 3; m_focusable = true; blinkCursor(); + + m_onAction = [this]() { this->callLuaField("onAction"); }; } UILineEditPtr UILineEdit::create() @@ -26,6 +28,11 @@ void UILineEdit::loadStyleFromOTML(const OTMLNodePtr& styleNode) UIWidget::loadStyleFromOTML(styleNode); setText(styleNode->valueAt("text", getText())); + + if(OTMLNodePtr node = styleNode->get("onAction")) { + g_lua.loadFunction(node->value(), "@" + node->source() + "[" + node->tag() + "]"); + luaSetField(node->tag()); + } } void UILineEdit::render() @@ -53,7 +60,7 @@ void UILineEdit::render() cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight()); else cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); - g_graphics.drawFilledRect(cursorRect, m_color); + g_graphics.drawFilledRect(cursorRect); } else if(ticks - m_cursorTicks >= 2*delay) { m_cursorTicks = ticks; } @@ -255,7 +262,7 @@ void UILineEdit::setCursorPos(int pos) } } -void UILineEdit::enableCursor(bool enable) +void UILineEdit::setCursorEnabled(bool enable) { if(enable) { m_cursorPos = 0; @@ -357,7 +364,10 @@ void UILineEdit::onKeyPress(UIKeyEvent& event) setCursorPos(0); else if(event.keyCode() == KC_END) // move cursor to last character setCursorPos(m_text.length()); - else if(event.keyChar() != 0) { + else if(event.keyCode() == KC_RETURN) { + if(m_onAction) + m_onAction(); + } else if(event.keyChar() != 0) { if(event.keyCode() != KC_TAB && event.keyCode() != KC_RETURN) appendCharacter(event.keyChar()); else diff --git a/src/framework/ui/uilineedit.h b/src/framework/ui/uilineedit.h index 8718bdf3..4efa67e1 100644 --- a/src/framework/ui/uilineedit.h +++ b/src/framework/ui/uilineedit.h @@ -18,8 +18,9 @@ public: void setText(const std::string& text); void setAlign(AlignmentFlag align); void setCursorPos(int pos); - void enableCursor(bool enable = true); + void setCursorEnabled(bool enable = true); + void clearText() { setText(""); } void moveCursor(bool right); void appendCharacter(char c); void removeCharacter(bool right); @@ -45,6 +46,7 @@ private: int m_startRenderPos; int m_cursorTicks; int m_textHorizontalMargin; + SimpleCallback m_onAction; std::vector m_glyphsCoords; std::vector m_glyphsTexCoords; diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index bc922689..c4dcacda 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -97,7 +97,7 @@ bool UIManager::importStyles(const std::string& file) importStyleFromOTML(styleNode); return true; } catch(std::exception& e) { - logError("ERROR: failed to import ui styles from '", file, "':\n", e.what()); + logError("failed to import ui styles from '", file, "':\n", e.what()); return false; } } @@ -118,7 +118,7 @@ void UIManager::importStyleFromOTML(const OTMLNodePtr& styleNode) auto it = m_styles.find(name); if(it != m_styles.end()) - logWarning("WARNING: style '", name, "' is being redefined"); + logWarning("style '", name, "' is being redefined"); OTMLNodePtr style = getStyle(base)->clone(); style->merge(styleNode); @@ -158,11 +158,9 @@ UIWidgetPtr UIManager::loadUI(const std::string& file) } } - // schedule onLoad events - widget->load(); return widget; } catch(std::exception& e) { - logError("ERROR: failed to load ui from '", file, "':\n", e.what()); + logError("failed to load ui from '", file, "':\n", e.what()); return nullptr; } } diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 26d248f6..eef070ee 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -21,8 +21,8 @@ UIWidget::UIWidget(UIWidgetType type) m_updateScheduled = false; m_opacity = 255; m_marginLeft = m_marginRight = m_marginTop = m_marginBottom = 0; - m_color = Color::white; - m_fontColor = Color::white; + m_backgroundColor = Color::white; + m_foregroundColor = Color::white; // generate an unique id, this is need because anchored layouts find widgets by id static unsigned long id = 1; @@ -33,13 +33,12 @@ UIWidget::~UIWidget() { //logTraceDebug(m_id); if(!m_destroyed) - logWarning("WARNING: widget '", m_id, "' was destructed without being explicit destroyed"); + logWarning("widget '", m_id, "' was destructed without being explicit destroyed"); } UIWidgetPtr UIWidget::create() { UIWidgetPtr widget(new UIWidget); - //widget->setStyle("Widget"); return widget; } @@ -48,6 +47,8 @@ void UIWidget::destroy() //TODO: onDestroy event // destroy only once if(!m_destroyed) { + releaseLuaFieldsTable(); + // clear additional reference m_lockedWidgets.clear(); m_focusedChild.reset(); @@ -68,7 +69,7 @@ void UIWidget::destroy() m_enabled = false; m_visible = false; } else - logWarning("WARNING: attempt to destroy widget '", m_id, "' again"); + logWarning("attempt to destroy widget '", m_id, "' again"); } void UIWidget::destroyCheck() @@ -81,21 +82,7 @@ void UIWidget::destroyCheck() // check for leaks upon widget destruction if(realUseCount > 0) - logWarning("WARNING: destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left"); -} - -void UIWidget::load() -{ - for(const UIWidgetPtr& child : m_children) - child->load(); - - // schedule onLoad - UIWidgetPtr self = asUIWidget(); - g_dispatcher.addEvent([self]() { - // this widget could be destroyed before the event happens - if(!self->isDestroyed()) - self->callLuaField("onLoad"); - }); + logWarning("destroyed widget with id '",m_id,"', but it still have ",realUseCount," references left"); } void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode) @@ -120,12 +107,12 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode) setFont(g_fonts.getFont(node->value())); } // font color - else if(node->tag() == "font-color") { - setFontColor(node->value()); + else if(node->tag() == "color") { + setForegroundColor(node->value()); } // color - else if(node->tag() == "color") { - setColor(node->value()); + else if(node->tag() == "background-color") { + setBackgroundColor(node->value()); } // opacity else if(node->tag() == "opacity") { @@ -197,9 +184,6 @@ void UIWidget::loadStyleFromOTML(const OTMLNodePtr& styleNode) luaSetField("onLoad"); } } - - if(!m_font) - m_font = g_fonts.getDefaultFont(); } void UIWidget::render() @@ -215,9 +199,13 @@ void UIWidget::render() if(child->getOpacity() < oldOpacity) g_graphics.setOpacity(child->getOpacity()); - g_graphics.bindColor(child->getColor()); + g_graphics.bindColor(child->getBackgroundColor()); child->render(); + // debug draw box + //g_graphics.bindColor(Color::green); + //g_graphics.drawBoundingRect(child->getGeometry()); + g_graphics.setOpacity(oldOpacity); } } @@ -227,8 +215,10 @@ void UIWidget::updateGeometry() { assert(!m_destroyed); - if(UILayoutPtr layout = getLayout()) + if(UILayoutPtr layout = getLayout()) { layout->updateWidget(asUIWidget()); + layout->updateWidgetChildren(asUIWidget()); + } } void UIWidget::setParent(const UIWidgetPtr& parent) @@ -260,7 +250,7 @@ void UIWidget::setStyle(const std::string& styleName) // forces layout recalculation updateGeometry(); } catch(std::exception& e) { - logError("ERROR: couldn't change widget '", m_id, "' style: ", e.what()); + logError("couldn't change widget '", m_id, "' style: ", e.what()); } } @@ -287,15 +277,6 @@ void UIWidget::setGeometry(const Rect& rect) } } -void UIWidget::lock() -{ - assert(!m_destroyed); - - UIWidgetPtr parent = getParent(); - if(parent) - parent->lockChild(asUIWidget()); -} - bool UIWidget::isEnabled() { if(!m_enabled) @@ -401,7 +382,7 @@ UIWidgetPtr UIWidget::getChildByPos(const Point& childPos) for(auto it = m_children.rbegin(); it != m_children.rend(); ++it) { const UIWidgetPtr& widget = (*it); - if(widget->getGeometry().contains(childPos)) + if(widget->isVisible() && widget->getGeometry().contains(childPos)) return widget; } @@ -533,14 +514,40 @@ void UIWidget::addChild(const UIWidgetPtr& childToAdd) m_children.push_back(childToAdd); childToAdd->setParent(asUIWidget()); - // updates child position - childToAdd->updateGeometry(); + // updates geometry + updateGeometry(); // focus it if there is no focused child yet if(!m_focusedChild && childToAdd->isFocusable()) focusChild(childToAdd, ActiveFocusReason); } +void UIWidget::insertChild(const UIWidgetPtr& childToInsert, int index) +{ + assert(!m_destroyed); + + if(!childToInsert) + return; + + assert(!hasChild(childToInsert)); + + if(index < 0) + index = m_children.size() + index -1; + + assert((uint)index <= m_children.size()); + + auto it = m_children.begin() + index; + m_children.insert(it, childToInsert); + childToInsert->setParent(asUIWidget()); + + // updates geometry + updateGeometry(); + + // focus it if there is no focused child yet + if(!m_focusedChild && childToInsert->isFocusable()) + focusChild(childToInsert, ActiveFocusReason); +} + void UIWidget::removeChild(const UIWidgetPtr& childToRemove) { assert(!m_destroyed); @@ -612,6 +619,9 @@ void UIWidget::lockChild(const UIWidgetPtr& childToLock) } m_lockedWidgets.push_front(childToLock); + + // move locked child to top + moveChildToTop(childToLock); } void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock) @@ -619,21 +629,21 @@ void UIWidget::unlockChild(const UIWidgetPtr& childToUnlock) assert(hasChild(childToUnlock)); auto it = std::find(m_lockedWidgets.begin(), m_lockedWidgets.end(), childToUnlock); - if(it != m_lockedWidgets.end()) { + if(it != m_lockedWidgets.end()) m_lockedWidgets.erase(it); - UIWidgetPtr newLockedWidget; - if(m_lockedWidgets.size() > 0) - newLockedWidget = m_lockedWidgets.front(); - for(const UIWidgetPtr& child : m_children) { - if(newLockedWidget) { - if(child == newLockedWidget) - child->setEnabled(true); - else - child->setEnabled(false); - } else + UIWidgetPtr newLockedWidget; + if(m_lockedWidgets.size() > 0) + newLockedWidget = m_lockedWidgets.front(); + + for(const UIWidgetPtr& child : m_children) { + if(newLockedWidget) { + if(child == newLockedWidget) child->setEnabled(true); - } + else + child->setEnabled(false); + } else + child->setEnabled(true); } } diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index 52558e9e..bce697a9 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -15,12 +15,12 @@ public: static UIWidgetPtr create(); + /// Must be called just after the widget creation + virtual void setup() { } + /// Remove this widget from parent then destroy it and its children virtual void destroy(); - /// Called after the widget is loaded from OTML file, to execute onLoad event - virtual void load(); - /// Load style from otml node virtual void loadStyleFromOTML(const OTMLNodePtr& styleNode); @@ -50,8 +50,8 @@ public: void setImage(const ImagePtr& image) { m_image = image; } virtual void setFont(const FontPtr& font) { m_font = font; } void setOpacity(int opacity) { m_opacity = opacity; } - void setColor(const Color& color) { m_color = color; } - void setFontColor(const Color& color) { m_fontColor = color; } + void setBackgroundColor(const Color& color) { m_backgroundColor = color; } + void setForegroundColor(const Color& color) { m_foregroundColor = color; } void setMarginLeft(int margin) { m_marginLeft = margin; updateGeometry(); } void setMarginRight(int margin) { m_marginRight = margin; updateGeometry(); } void setMarginTop(int margin) { m_marginTop = margin; updateGeometry(); } @@ -61,7 +61,6 @@ public: void show() { setVisible(true); } void disable() { setEnabled(false); } void enable() { setEnabled(true); } - void lock(); bool isEnabled(); bool isExplicitlyEnabled() const { return m_enabled; } @@ -88,8 +87,8 @@ public: ImagePtr getImage() const { return m_image; } FontPtr getFont() const { return m_font; } - Color getFontColor() const { return m_fontColor; } - Color getColor() const { return m_color; } + Color getForegroundColor() const { return m_foregroundColor; } + Color getBackgroundColor() const { return m_backgroundColor; } int getOpacity() const { return m_opacity; } int getMarginLeft() const { return m_marginLeft; } int getMarginRight() const { return m_marginRight; } @@ -108,6 +107,7 @@ public: UIWidgetPtr backwardsGetWidgetById(const std::string& id); void addChild(const UIWidgetPtr& childToAdd); + void insertChild(const UIWidgetPtr& childToInsert, int index); void removeChild(const UIWidgetPtr& childToRemove); void focusChild(const UIWidgetPtr& childToFocus, FocusReason reason); void focusNextChild(FocusReason reason); @@ -169,8 +169,8 @@ protected: ImagePtr m_image; FontPtr m_font; int m_opacity; - Color m_color; - Color m_fontColor; + Color m_backgroundColor; + Color m_foregroundColor; int m_marginLeft; int m_marginRight; int m_marginTop; diff --git a/src/framework/ui/uiwindow.cpp b/src/framework/ui/uiwindow.cpp index 7a25656c..3b18cd3c 100644 --- a/src/framework/ui/uiwindow.cpp +++ b/src/framework/ui/uiwindow.cpp @@ -55,7 +55,7 @@ void UIWindow::render() headTextRect.addLeft(-m_headMargin); else if(m_titleAlign & AlignRight) headTextRect.addRight(-m_headMargin); - m_font->renderText(m_title, headTextRect, m_titleAlign, m_fontColor); + m_font->renderText(m_title, headTextRect, m_titleAlign, m_foregroundColor); } // draw window body diff --git a/src/framework/util/color.h b/src/framework/util/color.h index 8c629bb7..93b1231a 100644 --- a/src/framework/util/color.h +++ b/src/framework/util/color.h @@ -2,7 +2,7 @@ #define COLOR_H #include "types.h" -#include +#include "tools.h" typedef uint32 RGBA; @@ -69,10 +69,19 @@ inline std::istream& operator>>(std::istream& in, Color& color) using namespace std; if(in.get() == '#') { - uint32 tmp; - in >> hex >> tmp; - color.setABGR(tmp); - in >> dec; + std::string tmp; + in >> tmp; + + if(tmp.length() == 6 || tmp.length() == 8) { + color.setRed((uint8)fw::hex2dec(tmp.substr(0, 2))); + color.setGreen((uint8)fw::hex2dec(tmp.substr(2, 2))); + color.setBlue((uint8)fw::hex2dec(tmp.substr(4, 2))); + if(tmp.length() == 8) + color.setAlpha((uint8)fw::hex2dec(tmp.substr(6, 2))); + else + color.setAlpha(255); + } else + in.seekg(-tmp.length()-1, ios_base::cur); } return in; } diff --git a/src/framework/util/logger.cpp b/src/framework/util/logger.cpp deleted file mode 100644 index 97683560..00000000 --- a/src/framework/util/logger.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include "logger.h" - -#include - -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); -} diff --git a/src/framework/util/logger.h b/src/framework/util/logger.h deleted file mode 100644 index 46ff6528..00000000 --- a/src/framework/util/logger.h +++ /dev/null @@ -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 diff --git a/src/framework/util/tools.h b/src/framework/util/tools.h index 7f083e18..a6dc5aa0 100644 --- a/src/framework/util/tools.h +++ b/src/framework/util/tools.h @@ -197,7 +197,7 @@ R unsafe_cast(const T& t, R def = R()) { try { return safe_cast(t); } catch(bad_cast& e) { - println(e.what()); + println("CAST ERROR: ", e.what()); return def; } } @@ -212,6 +212,21 @@ T fromstring(const std::string& str, T def = T()) { return unsafe_cast(str, def); } +inline std::string dec2hex(unsigned int num) { + std::string str; + std::ostringstream o; + o << std::hex << num; + str = o.str(); + return str; +} + +inline unsigned int hex2dec(const std::string& str) { + unsigned int num; + std::istringstream i(str); + i >> std::hex >> num; + return num; +} + // an empty string to use anywhere needed const static std::string empty_string; diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index bfe5f2e9..bb032485 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -60,8 +60,15 @@ void Creature::draw(int x, int y) } Rect healthRect = Rect(x - 14, y - 11, 27, 4); - g_graphics.drawBoundingRect(healthRect, Color::black); - g_graphics.drawFilledRect(healthRect.expanded(-1), healthColor); + + g_graphics.bindColor(Color::black); + g_graphics.drawBoundingRect(healthRect); + + g_graphics.bindColor(healthColor); + g_graphics.drawFilledRect(healthRect.expanded(-1)); + + // restore white color + g_graphics.bindColor(Color::white); } const ThingAttributes& Creature::getAttributes() diff --git a/src/otclient/core/datmanager.cpp b/src/otclient/core/datmanager.cpp index 188a4be6..0d7b8ebf 100644 --- a/src/otclient/core/datmanager.cpp +++ b/src/otclient/core/datmanager.cpp @@ -34,7 +34,7 @@ bool DatManager::load(const std::string& file) return true; } catch(std::exception& e) { - logError("ERROR: failed to load dat from '", file, "': ", e.what()); + logError("failed to load dat from '", file, "': ", e.what()); return false; } } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index c305c7ea..2ca48be2 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -48,9 +48,12 @@ void Map::draw(int x, int y) } // debug draws - g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32), Color::red); + g_graphics.bindColor(Color::red); + g_graphics.drawBoundingRect(Rect(7*32, 5*32, 32, 32)); m_framebuffer->unbind(); + + g_graphics.bindColor(Color::white); m_framebuffer->draw(Rect(x, y, g_graphics.getScreenSize())); } diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp index a7b453db..16e1161a 100644 --- a/src/otclient/core/spritemanager.cpp +++ b/src/otclient/core/spritemanager.cpp @@ -10,16 +10,16 @@ SpriteManager::SpriteManager() m_signature = 0; } -bool SpriteManager::load(const std::string &filename) +bool SpriteManager::load(const std::string& file) { try { - g_resources.loadFile(filename, m_fin); + g_resources.loadFile(file, m_fin); m_signature = fw::getu32(m_fin); m_spritesCount = fw::getu16(m_fin); m_sprites.resize(m_spritesCount); return true; } catch(std::exception& e) { - logError(e.what()); + logError("faile to load sprites from '", file, "': ", e.what()); return false; } } diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h index 2d487e13..c6d4575e 100644 --- a/src/otclient/core/spritemanager.h +++ b/src/otclient/core/spritemanager.h @@ -14,7 +14,7 @@ class SpriteManager public: SpriteManager(); - bool load(const std::string& filename); + bool load(const std::string& file); void unload(); uint32 getSignature() { return m_signature; } diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index 6cec5542..7f5c5d19 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -92,7 +92,7 @@ void OTClient::run() m_running = true; if(g_ui.getRootWidget()->getChildCount() == 0) { - logError("ERROR: there is no root widgets to display, the app will close"); + logError("there is no root widgets to display, the app will close"); m_stopping = true; } @@ -251,7 +251,7 @@ void OTClient::saveConfigurations() // saves user configuration if(!g_configs.save()) - logError("ERROR: configurations are lost because it couldn't be saved"); + logError("configurations are lost because it couldn't be saved"); } void OTClient::onClose() @@ -270,28 +270,43 @@ void OTClient::onResize(const Size& size) void OTClient::onPlatformEvent(const PlatformEvent& event) { - g_ui.inputEvent(event); + bool fireUi = true; if(event.type == EventKeyDown) { - if(!event.ctrl) { + if(!event.ctrl && !event.alt && !event.shift) { if(event.keycode == KC_UP) g_game.walk(DIRECTION_NORTH); - if(event.keycode == KC_RIGHT) + else if(event.keycode == KC_RIGHT) g_game.walk(DIRECTION_EAST); - if(event.keycode == KC_DOWN) + else if(event.keycode == KC_DOWN) g_game.walk(DIRECTION_SOUTH); - if(event.keycode == KC_LEFT) + else if(event.keycode == KC_LEFT) g_game.walk(DIRECTION_WEST); } - else { + else if(event.ctrl && !event.alt && !event.shift) { if(event.keycode == KC_UP) g_game.turn(DIRECTION_NORTH); - if(event.keycode == KC_RIGHT) + else if(event.keycode == KC_RIGHT) g_game.turn(DIRECTION_EAST); - if(event.keycode == KC_DOWN) + else if(event.keycode == KC_DOWN) g_game.turn(DIRECTION_SOUTH); - if(event.keycode == KC_LEFT) + else if(event.keycode == KC_LEFT) g_game.turn(DIRECTION_WEST); + else if(event.keycode == KC_APOSTROPHE) { + // TODO: move these events to lua + UIWidgetPtr console = g_ui.getRootWidget()->getChildById("consolePanel"); + if(!console->isVisible()) { + g_ui.getRootWidget()->lockChild(console); + console->setVisible(true); + } else { + g_ui.getRootWidget()->unlockChild(console); + console->setVisible(false); + } + fireUi = false; + } } } + + if(fireUi) + g_ui.inputEvent(event); } diff --git a/src/otclient/otclient.h b/src/otclient/otclient.h index fb8d6fba..5a7a8fd2 100644 --- a/src/otclient/otclient.h +++ b/src/otclient/otclient.h @@ -1,6 +1,7 @@ #ifndef OTCLIENT_H #define OTCLIENT_H +#include #include class OTClient : public PlatformListener