diff --git a/TODO b/TODO index e78600a8..e4b9fe8f 100644 --- a/TODO +++ b/TODO @@ -14,11 +14,10 @@ fix moving windows and tooltips conflicts todo display otclient icon in window bar remake otui styles states system padding - +break UILabel lines rename Game to g_game, etc implement Console key binding -fatal error if sprite load fails impl vertical sync, clipboard crash handler modify COnnection::poll() @@ -29,4 +28,13 @@ bind every global lua function in a static class use metatable for Point,Rect,Color,Size lua classes lua binder generator restore win32 platform -set special types for g_configs like lists/point/size \ No newline at end of file +set special types for g_configs like lists/point/size +restore ctrl+g and keybindings +create a class for reading binary files +handle corrupt errors in dat/spr + +create image class +use CoordsBuffer in font +cache into framebuffers +implement glbuffer for CoordsBuffer +use indices in CoordsBuffer \ No newline at end of file diff --git a/modules/addon_console/commands.lua b/modules/addon_console/commands.lua new file mode 100644 index 00000000..03ddf63d --- /dev/null +++ b/modules/addon_console/commands.lua @@ -0,0 +1,5 @@ +function dumpWidgets() + for i=1,UI.root:getChildCount() do + print(UI.root:getChildByIndex(i):getId()) + end +end \ No newline at end of file diff --git a/modules/addon_console/console.lua b/modules/addon_console/console.lua index 57dd9802..41a8e222 100644 --- a/modules/addon_console/console.lua +++ b/modules/addon_console/console.lua @@ -34,7 +34,7 @@ local function completeCommand() local cursorPos = commandLineEdit:getCursorPos() if cursorPos == 0 then return end - local commandBegin = string.sub(commandLineEdit:getText(), 1, cursorPos) + local commandBegin = commandLineEdit:getText():sub(1, cursorPos) local possibleCommands = {} -- create a list containing all globals @@ -43,7 +43,7 @@ local function completeCommand() -- match commands for k,v in pairs(allVars) do - if string.sub(k, 1, cursorPos) == commandBegin then + if k:sub(1, cursorPos) == commandBegin then table.insert(possibleCommands, k) end end @@ -63,9 +63,9 @@ local function completeCommand() if #possibleCommands[1] < cursorPos then break end - expandedComplete = commandBegin .. string.sub(possibleCommands[1], cursorPos, cursorPos) + expandedComplete = commandBegin .. possibleCommands[1]:sub(cursorPos, cursorPos) for i,v in ipairs(possibleCommands) do - if string.sub(v, 1, #expandedComplete) ~= expandedComplete then + if v:sub(1, #expandedComplete) ~= expandedComplete then done = true end end diff --git a/modules/addon_console/console.otmod b/modules/addon_console/console.otmod index bc6972b1..2a1634be 100644 --- a/modules/addon_console/console.otmod +++ b/modules/addon_console/console.otmod @@ -8,11 +8,9 @@ Module autoLoad: true autoLoadPriority: 20 - dependencies: - - core - onLoad: | require 'console' + require 'commands' Console.init() return true diff --git a/modules/client/client.lua b/modules/client/client.lua index 99ae68a5..8d074c04 100644 --- a/modules/client/client.lua +++ b/modules/client/client.lua @@ -3,7 +3,7 @@ Client = { } -- TODO: load and save configurations function Client.init() g_window.move({ x=220, y=220 }) - g_window.resize({ width=800, height=600 }) + g_window.resize({ width=800, height=480 }) g_window.setTitle('OTClient') g_window.setIcon('clienticon.png') return true diff --git a/modules/client_entergame/entergame.lua b/modules/client_entergame/entergame.lua index 93caf339..ba38bb3c 100644 --- a/modules/client_entergame/entergame.lua +++ b/modules/client_entergame/entergame.lua @@ -23,8 +23,8 @@ local function onError(protocol, error) end local function onMotd(protocol, motd) - motdNumber = tonumber(string.sub(motd, 0, string.find(motd, "\n"))) - motdMessage = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd)) + motdNumber = tonumber(motd:sub(0, motd:find("\n"))) + motdMessage = motd:sub(motd:find("\n") + 1, #motd) TopMenu.getButton('motdButton'):show() end diff --git a/modules/client_options/options.lua b/modules/client_options/options.lua index 30fa3b79..68f6060a 100644 --- a/modules/client_options/options.lua +++ b/modules/client_options/options.lua @@ -7,7 +7,7 @@ local vsyncEnabled = false function getConfig(name, default) if g_configs.exists(name) then - local val = string.trim(g_configs.get(name)) + local val = g_configs.get(name):trim() if val == 'true' or val == 'false' then return toboolean(val) else diff --git a/modules/core_scripts/constants.lua b/modules/core_scripts/const.lua similarity index 96% rename from modules/core_scripts/constants.lua rename to modules/core_scripts/const.lua index b40cbb10..2783a32d 100644 --- a/modules/core_scripts/constants.lua +++ b/modules/core_scripts/const.lua @@ -1,4 +1,3 @@ --- AnchorEdge AnchorNone = 0 AnchorTop = 1 AnchorBottom = 2 @@ -15,9 +14,6 @@ LogFatal = 4 ActiveFocusReason = 2 -EmptyFunction = function() end - --- KeyCodes KeyUnknown = 0 KeyEscape = 1 KeyTab = 2 @@ -57,7 +53,7 @@ KeyLeftParen = 40 -- ( KeyRightParen = 41 -- ) KeyAsterisk = 42 -- * KeyPlus = 43 -- + -KeyComma = 44 -- +KeyComma = 44 -- , KeyMinus = 45 -- - KeyPeriod = 46 -- . KeySlash = 47 -- / diff --git a/modules/core_scripts/core_scripts.otmod b/modules/core_scripts/core_scripts.otmod index 8c52ba30..a4478608 100644 --- a/modules/core_scripts/core_scripts.otmod +++ b/modules/core_scripts/core_scripts.otmod @@ -7,10 +7,14 @@ Module onLoad: | require 'ext/table' require 'ext/string' - require 'constants' + require 'util/point' + require 'util/size' + require 'util/color' + require 'util/rect' + require 'const' require 'util' require 'dispatcher' require 'widget' require 'ui' - require 'gfx' + require 'effects' return true diff --git a/modules/core_scripts/dispatcher.lua b/modules/core_scripts/dispatcher.lua index bea374b8..ee13f5a0 100644 --- a/modules/core_scripts/dispatcher.lua +++ b/modules/core_scripts/dispatcher.lua @@ -1,43 +1,33 @@ local eventId = 0 -local eventsTable = { } -local orig = { scheduleEvent = scheduleEvent, - addEvent = addEvent } +local eventList = {} --- fix original scheduleEvent function scheduleEvent(func, delay) eventId = eventId + 1 local id = eventId local function proxyFunc() - if eventsTable[id] then - func() - eventsTable[id] = nil + if eventList[id] then + if eventList[id].active then + func() + end + eventList[id] = nil end end - eventsTable[id] = proxyFunc - orig.scheduleEvent(proxyFunc, delay) + eventList[id] = { func = proxyFunc, active = true } + if delay and delay > 0 then + g_dispatcher.scheduleEvent(proxyFunc, delay) + else + g_dispatcher.addEvent(proxyFunc, false) + end return id end --- FIXME: the event function can be collected --- and the dispatcher would call an invalid function, generating an warning +function addEvent(func) + return scheduleEvent(func, 0) +end + function removeEvent(id) - if id and eventsTable[id] then - eventsTable[id] = nil + if id and eventList[id] then + eventList[id].active = false return true end end - --- fix original addEvent -function addEvent(func) - eventId = eventId + 1 - local id = eventId - local function proxyFunc() - if eventsTable[id] then - func() - eventsTable[id] = nil - end - end - eventsTable[id] = proxyFunc - orig.addEvent(proxyFunc) - return id -end \ No newline at end of file diff --git a/modules/core_scripts/gfx.lua b/modules/core_scripts/effects.lua similarity index 85% rename from modules/core_scripts/gfx.lua rename to modules/core_scripts/effects.lua index af0aa0db..b92307a8 100644 --- a/modules/core_scripts/gfx.lua +++ b/modules/core_scripts/effects.lua @@ -1,6 +1,6 @@ -GFX = { } +Effects = {} -function GFX.fadeIn(widget, time, elapsed) +function Effects.fadeIn(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end widget:setOpacity(math.min((255*elapsed)/time, 255)) @@ -11,7 +11,7 @@ function GFX.fadeIn(widget, time, elapsed) end end -function GFX.fadeOut(widget, time, elapsed) +function Effects.fadeOut(widget, time, elapsed) if not elapsed then elapsed = 0 end if not time then time = 250 end widget:setOpacity((255*(time - elapsed))/time) diff --git a/modules/core_scripts/ext/string.lua b/modules/core_scripts/ext/string.lua index a619a7a9..b3bb10b6 100644 --- a/modules/core_scripts/ext/string.lua +++ b/modules/core_scripts/ext/string.lua @@ -13,12 +13,12 @@ function string:starts(start) return self:sub(1, #start) == start end -function string.trim(str) - return str:match'^%s*(.*%S)' or '' +function string:trim() + return self:match('^%s*(.*%S)') or '' end function toboolean(str) - str = string.trim(str) + str = str:trim() if str == '1' or str == 'true' then return true end diff --git a/modules/core_scripts/ext/table.lua b/modules/core_scripts/ext/table.lua index 8627cc5f..5a8e8e68 100644 --- a/modules/core_scripts/ext/table.lua +++ b/modules/core_scripts/ext/table.lua @@ -1,7 +1,7 @@ function table.dump(t, depth) if not depth then depth = 0 end for k,v in pairs(t) do - str = string.rep(' ', depth * 2) .. k .. ': ' + str = (' '):rep(depth * 2) .. k .. ': ' if type(v) ~= "table" then print(str .. tostring(v)) else diff --git a/modules/core_scripts/util.lua b/modules/core_scripts/util.lua index 9bf33688..cd65806e 100644 --- a/modules/core_scripts/util.lua +++ b/modules/core_scripts/util.lua @@ -6,10 +6,8 @@ function print(...) Logger.log(LogInfo, msg) end -function createEnvironment() - local env = { } - setmetatable(env, { __index = _G} ) - return env +function fatal(msg) + Logger.log(LogFatal, msg) end function connect(object, signalsAndSlots, pushFront) @@ -28,10 +26,10 @@ function connect(object, signalsAndSlots, pushFront) end end -function dumpWidgets() - for i=1,UI.root:getChildCount() do - print(UI.root:getChildByIndex(i):getId()) - end +function createEnvironment() + local env = { } + setmetatable(env, { __index = _G} ) + return env end function getCallingScriptSourcePath(depth) diff --git a/modules/core_scripts/ext/color.lua b/modules/core_scripts/util/color.lua similarity index 100% rename from modules/core_scripts/ext/color.lua rename to modules/core_scripts/util/color.lua diff --git a/modules/core_scripts/ext/point.lua b/modules/core_scripts/util/point.lua similarity index 100% rename from modules/core_scripts/ext/point.lua rename to modules/core_scripts/util/point.lua diff --git a/modules/core_scripts/ext/rect.lua b/modules/core_scripts/util/rect.lua similarity index 100% rename from modules/core_scripts/ext/rect.lua rename to modules/core_scripts/util/rect.lua diff --git a/modules/core_scripts/ext/size.lua b/modules/core_scripts/util/size.lua similarity index 100% rename from modules/core_scripts/ext/size.lua rename to modules/core_scripts/util/size.lua diff --git a/modules/core_scripts/widget.lua b/modules/core_scripts/widget.lua index edcc0b09..88e82ca0 100644 --- a/modules/core_scripts/widget.lua +++ b/modules/core_scripts/widget.lua @@ -16,4 +16,4 @@ function UIWidget:setMargin(...) self:setMarginBottom(params[3]) self:setMarginLeft(params[4]) end -end \ No newline at end of file +end diff --git a/modules/core_widgets/messagebox/messagebox.lua b/modules/core_widgets/messagebox/messagebox.lua index 6486371a..cd4704ba 100644 --- a/modules/core_widgets/messagebox/messagebox.lua +++ b/modules/core_widgets/messagebox/messagebox.lua @@ -28,7 +28,7 @@ function MessageBox.create(title, text, flags) if flags == MessageBoxOk then buttonRight:setText("Ok") - box.onOk = EmptyFunction + box.onOk = function() end buttonRight.onClick = function() box.onOk() box:destroy() @@ -37,7 +37,7 @@ function MessageBox.create(title, text, flags) window.onEscape = buttonRight.onClick elseif flags == MessageBoxCancel then buttonRight:setText("Cancel") - box.onCancel = EmptyFunction + box.onCancel = function() end buttonRight.onClick = function() box.onCancel() box:destroy() diff --git a/modules/core_widgets/tooltip/tooltip.lua b/modules/core_widgets/tooltip/tooltip.lua index 0dcc88ba..20630da0 100644 --- a/modules/core_widgets/tooltip/tooltip.lua +++ b/modules/core_widgets/tooltip/tooltip.lua @@ -28,7 +28,7 @@ function ToolTip.display(text) local size = label:getSize() size.width = size.width + 4 size.height = size.height + 4 - currentToolTip:setSize(size) + currentToolTip:resize(size) moveToolTip(currentToolTip) end end diff --git a/modules/outfit.frag b/modules/outfit.frag new file mode 100644 index 00000000..e1df99fa --- /dev/null +++ b/modules/outfit.frag @@ -0,0 +1,49 @@ +uniform float opacity; +uniform vec4 color; +uniform float ticks; + +uniform sampler2D texture; // outfit texture +varying vec2 textureCoords; // outfit texture coords +uniform sampler2D maskTexture; // outfit color mask + +uniform vec4 headColor; +uniform vec4 bodyColor; +uniform vec4 legsColor; +uniform vec4 feetColor; + +vec4 calcPixel(vec2 texCoord) +{ + vec4 pixel = texture2D(texture, texCoord); + vec4 maskColor = texture2D(maskTexture, texCoord); + + vec4 outColor = vec4(0); + if(maskColor.r == 1.0 && maskColor.g == 1.0) { + outColor = headColor; + } else if(maskColor.r == 1.0) { + outColor = bodyColor; + } else if(maskColor.g == 1.0) { + outColor = legsColor; + } else if(maskColor.b == 1.0) { + outColor = feetColor; + } + + if(outColor.a != 0.0) + pixel = pixel * outColor; + return pixel; +} +void main() +{ + vec4 pixel = calcPixel(textureCoords); + int num = 16; + + vec4 sum = vec4(0); + int i, j; + for(i=-num/2;i #include #include +#include #include Application *g_app = nullptr; @@ -135,7 +136,6 @@ void Application::terminate() // terminate graphics if(m_appFlags & Fw::AppEnableGraphics) { g_ui.terminate(); - g_graphics.terminate(); g_window.terminate(); } @@ -222,8 +222,8 @@ void Application::render() void Application::resize(const Size& size) { - g_graphics.resize(size); g_ui.resize(size); + g_graphics.resize(size); } void Application::inputEvent(const InputEvent& event) diff --git a/src/framework/const.h b/src/framework/const.h index 1921afa5..fff914aa 100644 --- a/src/framework/const.h +++ b/src/framework/const.h @@ -178,12 +178,6 @@ namespace Fw LogFatal }; - enum BlendFunc { - BlendDefault, - BlendColorzing, - BlendParticles - }; - enum AspectRatioMode { IgnoreAspectRatio, KeepAspectRatio, diff --git a/src/framework/core/module.cpp b/src/framework/core/module.cpp index a6bb2377..ea2361ae 100644 --- a/src/framework/core/module.cpp +++ b/src/framework/core/module.cpp @@ -79,15 +79,13 @@ bool Module::load() } } - if(m_loadCallback) { - m_loaded = m_loadCallback(); - if(!m_loaded) { - logError("Unable to load module '", m_name, "' because its onLoad event returned false"); - return false; - } + if(m_loadCallback && !m_loadCallback()) { + logError("Unable to load module '", m_name, "' because its onLoad event returned false"); + return false; } logInfo("Loaded module '", m_name, "'"); + m_loaded = true; return true; } diff --git a/src/framework/graphics/animatedtexture.cpp b/src/framework/graphics/animatedtexture.cpp index d84077b6..7d200e51 100644 --- a/src/framework/graphics/animatedtexture.cpp +++ b/src/framework/graphics/animatedtexture.cpp @@ -29,7 +29,7 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra Texture(), m_numFrames(numFrames) { - m_size.setSize(width, height); + m_size.resize(width, height); m_framesTextureId.resize(numFrames); m_framesDelay.resize(numFrames); diff --git a/src/framework/graphics/borderimage.cpp b/src/framework/graphics/borderimage.cpp index 2fa82dca..1f547c2b 100644 --- a/src/framework/graphics/borderimage.cpp +++ b/src/framework/graphics/borderimage.cpp @@ -133,72 +133,72 @@ BorderImagePtr BorderImage::loadFromOTML(const OTMLNodePtr& borderImageNode) void BorderImage::draw(const Rect& screenCoords) { //TODO: borderimage drawing could be optimized by caching the render into a texture + if(screenCoords != m_cachedScreenCoords) { + m_cachedScreenCoords = screenCoords; + m_coordsBuffer.clear(); - Rect rectCoords; - Size centerSize = screenCoords.size() - m_bordersSize; + Rect rectCoords; + Size centerSize = screenCoords.size() - m_bordersSize; - g_graphics.bindTexture(m_texture); - g_graphics.startDrawing(); + // first the center + if(centerSize.area() > 0) { + rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), + screenCoords.top() + m_topBorderTexCoords.height(), + centerSize); + m_coordsBuffer.addRepeatedRects(rectCoords, m_centerTexCoords); + } - // first the center - if(centerSize.area() > 0) { - rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), - screenCoords.top() + m_topBorderTexCoords.height(), - centerSize); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords); + // top left corner + rectCoords = Rect(screenCoords.topLeft(), + m_topLeftCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topLeftCornerTexCoords); + + // top + rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), + screenCoords.topLeft().y, + centerSize.width(), + m_topBorderTexCoords.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topBorderTexCoords); + + + // top right corner + rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), + screenCoords.top(), + m_topRightCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_topRightCornerTexCoords); + + // left + rectCoords = Rect(screenCoords.left(), + screenCoords.top() + m_topLeftCornerTexCoords.height(), + m_leftBorderTexCoords.width(), + centerSize.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_leftBorderTexCoords); + + // right + rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), + screenCoords.top() + m_topRightCornerTexCoords.height(), + m_rightBorderTexCoords.width(), + centerSize.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_rightBorderTexCoords); + + // bottom left corner + rectCoords = Rect(screenCoords.left(), + screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), + m_bottomLeftCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomLeftCornerTexCoords); + + // bottom + rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), + screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), + centerSize.width(), + m_bottomBorderTexCoords.height()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomBorderTexCoords); + + // bottom right corner + rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), + screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), + m_bottomRightCornerTexCoords.size()); + m_coordsBuffer.addRepeatedRects(rectCoords, m_bottomRightCornerTexCoords); } - - // top left corner - rectCoords = Rect(screenCoords.topLeft(), - m_topLeftCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords); - - // top - rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), - screenCoords.topLeft().y, - centerSize.width(), - m_topBorderTexCoords.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords); - - - // top right corner - rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), - screenCoords.top(), - m_topRightCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords); - - // left - rectCoords = Rect(screenCoords.left(), - screenCoords.top() + m_topLeftCornerTexCoords.height(), - m_leftBorderTexCoords.width(), - centerSize.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords); - - // right - rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), - screenCoords.top() + m_topRightCornerTexCoords.height(), - m_rightBorderTexCoords.width(), - centerSize.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords); - - // bottom left corner - rectCoords = Rect(screenCoords.left(), - screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), - m_bottomLeftCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords); - - // bottom - rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), - screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), - centerSize.width(), - m_bottomBorderTexCoords.height()); - g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords); - - // bottom right corner - rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), - screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), - m_bottomRightCornerTexCoords.size()); - g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords); - - g_graphics.stopDrawing(); + g_painter.drawTextureCoords(m_coordsBuffer, m_texture); } \ No newline at end of file diff --git a/src/framework/graphics/coordsbuffer.cpp b/src/framework/graphics/coordsbuffer.cpp new file mode 100644 index 00000000..1f59c682 --- /dev/null +++ b/src/framework/graphics/coordsbuffer.cpp @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "coordsbuffer.h" + +void CoordsBuffer::clear() +{ + m_destRects.reset(); + m_srcRects.reset(); + m_textureCoords.clear(); + m_vertices.clear(); + m_updateCache = true; +} + +void CoordsBuffer::addRect(const Rect& dest) +{ + m_destRects << dest; + m_updateCache = true; +} + +void CoordsBuffer::addRect(const Rect& dest, const Rect& src) +{ + m_destRects << dest; + m_srcRects << src; + m_updateCache = true; +} + +void CoordsBuffer::addBoudingRect(const Rect& dest, int innerLineWidth) +{ + int left = dest.left(); + int right = dest.right(); + int top = dest.top(); + int bottom = dest.bottom(); + int width = dest.width(); + int height = dest.height(); + int w = innerLineWidth; + + addRect(Rect(left, top, width - w, w)); // top + addRect(Rect(right - w + 1, top, w, height - w)); // right + addRect(Rect(left + w, bottom - w + 1, width - w, w)); // bottom + addRect(Rect(left, top + w, w, height - w)); // left + m_updateCache = true; +} + +void CoordsBuffer::addRepeatedRects(const Rect& dest, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty()) + return; + + Rect virtualDest(0, 0, dest.size()); + for(int y = 0; y <= virtualDest.height(); y += src.height()) { + for(int x = 0; x <= virtualDest.width(); x += src.width()) { + Rect partialDest(x, y, src.size()); + Rect partialSrc(src); + + // partialCoords to screenCoords bottomRight + if(partialDest.bottom() > virtualDest.bottom()) { + partialSrc.setBottom(partialSrc.bottom() + (virtualDest.bottom() - partialDest.bottom())); + partialDest.setBottom(virtualDest.bottom()); + } + if(partialDest.right() > virtualDest.right()) { + partialSrc.setRight(partialSrc.right() + (virtualDest.right() - partialDest.right())); + partialDest.setRight(virtualDest.right()); + } + + partialDest.translate(dest.topLeft()); + m_destRects << partialDest; + m_srcRects << partialSrc; + } + } + m_updateCache = true; +} + +void CoordsBuffer::cacheVertexArrays() +{ + if(!m_updateCache) + return; + + int numDestRects = m_destRects.size(); + int numSrcRects = m_srcRects.size(); + m_vertices.clear(); + m_textureCoords.clear(); + + for(int i=0;i + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef COORDSBUFFER_H +#define COORDSBUFFER_H + +#include "vertexarray.h" + +class CoordsBuffer +{ +public: + void clear(); + + // no texture + void addRect(const Rect& dest); + void addBoudingRect(const Rect& dest, int innerLineWidth); + + // textured + void addRect(const Rect& dest, const Rect& src); + void addRepeatedRects(const Rect& dest, const Rect& src); + + void cacheVertexArrays(); + + GLfloat *getVertices() const { return m_vertices.vertices(); } + GLfloat *getTextureCoords() const { return m_textureCoords.vertices(); } + int getVertexCount() const { return m_vertices.vertexCount(); } + int getTextureCoordsCount() const { return m_textureCoords.vertexCount(); } + +private: + DataBuffer m_destRects; + DataBuffer m_srcRects; + VertexArray m_vertices; + VertexArray m_textureCoords; + Boolean m_updateCache; +}; + +#endif diff --git a/src/framework/graphics/declarations.h b/src/framework/graphics/declarations.h index 54a14cac..132d6343 100644 --- a/src/framework/graphics/declarations.h +++ b/src/framework/graphics/declarations.h @@ -32,6 +32,9 @@ class Font; class Image; class BorderImage; class FrameBuffer; +class Shader; +class ShaderProgram; +class PainterShaderProgram; typedef std::weak_ptr TextureWeakPtr; @@ -41,5 +44,9 @@ typedef std::shared_ptr FontPtr; typedef std::shared_ptr ImagePtr; typedef std::shared_ptr BorderImagePtr; typedef std::shared_ptr FrameBufferPtr; +typedef std::shared_ptr ShaderPtr; +typedef std::shared_ptr ShaderProgramPtr; +typedef std::shared_ptr PainterShaderProgramPtr; +typedef std::vector ShaderList; #endif diff --git a/src/framework/graphics/font.cpp b/src/framework/graphics/font.cpp index 29a4246c..ac7c0cef 100644 --- a/src/framework/graphics/font.cpp +++ b/src/framework/graphics/font.cpp @@ -64,7 +64,7 @@ void Font::renderText(const std::string& text, const Point& startPos, const Color& color) { - Size boxSize = g_graphics.getScreenSize() - startPos.toSize(); + Size boxSize = g_graphics.getViewportSize() - startPos.toSize(); Rect screenCoords(startPos, boxSize); renderText(text, screenCoords, Fw::AlignTopLeft, color); } @@ -85,9 +85,7 @@ void Font::renderText(const std::string& text, Size textBoxSize; const std::vector& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); - g_graphics.bindColor(color); - g_graphics.bindTexture(m_texture); - g_graphics.startDrawing(); + g_painter.setColor(color); for(int i = 0; i < textLenght; ++i) { int glyph = (uchar)text[i]; @@ -149,10 +147,8 @@ void Font::renderText(const std::string& text, } // render glyph - g_graphics.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); + g_painter.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); } - - g_graphics.stopDrawing(); } const std::vector& Font::calculateGlyphsPositions(const std::string& text, @@ -172,7 +168,7 @@ const std::vector& Font::calculateGlyphsPositions(const std::string& text // return if there is no text if(textLength == 0) { if(textBoxSize) - textBoxSize->setSize(0,m_glyphHeight); + textBoxSize->resize(0,m_glyphHeight); return glyphsPositions; } @@ -280,6 +276,6 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize) lastColumnFilledPixels = columnFilledPixels; } // store glyph size - m_glyphsSize[glyph].setSize(width, m_glyphHeight); + m_glyphsSize[glyph].resize(width, m_glyphHeight); } } diff --git a/src/framework/graphics/framebuffer.cpp b/src/framework/graphics/framebuffer.cpp index 3cd16bdb..8d7ba498 100644 --- a/src/framework/graphics/framebuffer.cpp +++ b/src/framework/graphics/framebuffer.cpp @@ -26,110 +26,52 @@ FrameBuffer::FrameBuffer(int width, int height) { - m_fbo = 0; - // create FBO texture m_texture = TexturePtr(new Texture(width, height, 4)); m_texture->enableBilinearFilter(); - // use FBO ext only if supported - if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) { - m_fallbackOldImp = false; + // generate FBO + glGenFramebuffers(1, &m_fbo); + if(!m_fbo) + logFatal("Unable to create framebuffer object"); - // generate FBO - glGenFramebuffers(1, &m_fbo); - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); - // attach 2D texture to this FBO - glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0); + // attach 2D texture to this FBO + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0); - GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); - switch(status) { - case GL_FRAMEBUFFER_COMPLETE_EXT: - //ok - break; - default: // fallback to old implementation - m_fallbackOldImp = true; - break; - } + GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if(status != GL_FRAMEBUFFER_COMPLETE) + logFatal("Unable to create framebuffer object"); - // restore back buffer - glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); - } else { - // otherwise fallback to copy texture from screen implementation - m_fallbackOldImp = true; - } - - if(m_fallbackOldImp) - logInfo("Framebuffers not supported, falling back to old implementation."); + // restore back buffer + glBindFramebuffer(GL_FRAMEBUFFER, 0); } FrameBuffer::~FrameBuffer() { - if(m_fbo) - glDeleteFramebuffers(1, &m_fbo); + glDeleteFramebuffers(1, &m_fbo); } void FrameBuffer::bind() { - if(!m_fallbackOldImp) { - // bind framebuffer - glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo); - } else { - int screenWidth = g_graphics.getScreenSize().width(); - int screenHeight = g_graphics.getScreenSize().height(); - - if(!m_screenBackup || m_screenBackup->getSize() != g_graphics.getScreenSize()) - m_screenBackup = TexturePtr(new Texture(screenWidth, screenHeight, 4)); - - // save screen state - glBindTexture(GL_TEXTURE_2D, m_screenBackup->getId()); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight); - } - - // setup framebuffer viewport - glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight()); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, m_texture->getWidth(), m_texture->getHeight(), 0, -1, 1); - - // back to model view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // clear framebuffer - glClearColor(0.0, 0.0, 0.0, 1.0); + glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glClear(GL_COLOR_BUFFER_BIT); + glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight()); + g_painter.updateProjectionMatrix(m_texture->getSize(), true); } -void FrameBuffer::unbind() +void FrameBuffer::release() { - if(!m_fallbackOldImp) { - // bind back buffer again - glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); - glDrawBuffer(GL_BACK); - glReadBuffer(GL_BACK); + // bind back buffer again + glBindFramebuffer(GL_FRAMEBUFFER, 0); - // restore graphics viewport - g_graphics.restoreViewport(); - } else { - // copy screen to texture - glBindTexture(GL_TEXTURE_2D, m_texture->getId()); - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_texture->getWidth(), m_texture->getHeight()); - - // restore graphics viewport - g_graphics.restoreViewport(); - - // restore screen - glClearColor(0.0, 0.0, 0.0, 1.0); - glClear(GL_COLOR_BUFFER_BIT); - g_graphics.drawTexturedRect(Rect(Point(0,0), g_graphics.getScreenSize()), m_screenBackup, Rect(), true); - } + // restore graphics viewport + glViewport(0, 0, g_graphics.getViewportSize().width(), g_graphics.getViewportSize().height()); + g_painter.updateProjectionMatrix(g_graphics.getViewportSize()); } -void FrameBuffer::draw(const Rect& screenCoords, const Rect& framebufferCoords) +void FrameBuffer::draw(const Rect& dest) { - g_graphics.drawTexturedRect(screenCoords, m_texture, framebufferCoords, true); + g_painter.drawTexturedRect(dest, m_texture); } diff --git a/src/framework/graphics/framebuffer.h b/src/framework/graphics/framebuffer.h index 182ef1a9..16ce6cdc 100644 --- a/src/framework/graphics/framebuffer.h +++ b/src/framework/graphics/framebuffer.h @@ -32,8 +32,8 @@ public: virtual ~FrameBuffer(); void bind(); - void unbind(); - void draw(const Rect& screenCoords, const Rect& framebufferCoords = Rect()); + void release(); + void draw(const Rect& dest); TexturePtr getTexture() { return m_texture; } diff --git a/src/framework/graphics/glbuffer.cpp b/src/framework/graphics/glbuffer.cpp new file mode 100644 index 00000000..fd2e1cad --- /dev/null +++ b/src/framework/graphics/glbuffer.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "glbuffer.h" + +GLBuffer::GLBuffer() +{ + glGenBuffers(1, &m_id); + if(!m_id) + logFatal("Unable to create a simple GL buffer"); +} + +void GLBuffer::bind() +{ + gl +} + +void GLBuffer::release() +{ + +} + diff --git a/src/framework/graphics/glbuffer.h b/src/framework/graphics/glbuffer.h new file mode 100644 index 00000000..6977363b --- /dev/null +++ b/src/framework/graphics/glbuffer.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef GLBUFFER_H +#define GLBUFFER_H + +#include "declarations.h" + +class GLBuffer +{ +public: + GLBuffer(); + ~GLBuffer(); + + void write(const + void bind(); + void release(); + + GLuint bufferId(); + +private: + GLuint m_id; +}; + +#endif diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 3033e4bb..5e342587 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -30,310 +30,47 @@ Graphics g_graphics; void Graphics::init() { // setup opengl - glEnable(GL_ALPHA_TEST); // enable alpha by default - glAlphaFunc(GL_GREATER, 0.0f); // default alpha func - glDisable(GL_DEPTH_TEST); // we are rendering 2D only, we don't need depth buffer - glEnable(GL_TEXTURE_2D); // enable textures by default - glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); - glShadeModel(GL_SMOOTH); glEnable(GL_BLEND); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); logInfo("GPU ", glGetString(GL_RENDERER)); logInfo("OpenGL ", glGetString(GL_VERSION)); - m_drawing = false; - m_opacity = 255; + //if(!isExtensionSupported("GL_ARB_framebuffer_object")) + // logFatal("Your graphics card is not supported."); + m_emptyTexture = TexturePtr(new Texture); - bindColor(Fw::white); - bindBlendFunc(Fw::BlendDefault); + g_painter.init(); } void Graphics::terminate() { g_fonts.releaseFonts(); + g_painter.terminate(); m_emptyTexture.reset(); } bool Graphics::isExtensionSupported(const char *extension) { - const GLubyte *extensions = NULL; - const GLubyte *start; - GLubyte *where, *terminator; - where = (GLubyte *)strchr(extension, ' '); - - if(where || *extension == '\0') - return 0; - - extensions = glGetString(GL_EXTENSIONS); - - start = extensions; - while(true) { - where = (GLubyte *) strstr((const char *)start, extension); - if(!where) - break; - - terminator = where + strlen(extension); - - if(where == start || *(where - 1) == ' ') - if(*terminator == ' ' || *terminator == '\0') - return 1; - - start = terminator; - } - return 0; + std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS); + auto extensions = Fw::split(extensionsString); + return std::find(extensions.begin(), extensions.end(), extension) != extensions.end(); } void Graphics::resize(const Size& size) { - m_screenSize = size; - restoreViewport(); -} - -void Graphics::restoreViewport() -{ - const int& width = m_screenSize.width(); - const int& height = m_screenSize.height(); - - // resize gl viewport - glViewport(0, 0, width, height); - - /* - 0,0---------0,w - | | - | | - | | - h,0---------h,w - */ - // setup view region like above - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0.0f, width, height, 0.0f, -1, 1); - - // back to model view - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); + glViewport(0, 0, size.width(), size.height()); + g_painter.updateProjectionMatrix(size); + m_viewportSize = size; } void Graphics::beginRender() { glClear(GL_COLOR_BUFFER_BIT); - glLoadIdentity(); } void Graphics::endRender() { - assert(!m_drawing); -} - -void Graphics::drawTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords, - bool upsideDown) -{ - if(screenCoords.isEmpty() || texture->getId() == 0) - return; - - // rect correction for opengl - int right = screenCoords.right() + 1; - int bottom = screenCoords.bottom() + 1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - float textureRight; - float textureBottom; - float textureTop; - float textureLeft; - const Size& textureSize = texture->getGlSize(); - - if(textureCoords.isEmpty()) { - textureRight = texture->getWidth() / (float)textureSize.width(); - if(upsideDown) { - textureBottom = 0.0f; - textureTop = texture->getHeight() / (float)textureSize.height(); - } else { - textureBottom = texture->getHeight() / (float)textureSize.height(); - textureTop = 0.0f; - } - textureLeft = 0.0f; - } else { - textureRight = (textureCoords.right() + 1) / (float)textureSize.width(); - if(upsideDown) { - textureTop = (textureCoords.bottom() + 1) / (float)textureSize.height(); - textureBottom = textureCoords.top() / (float)textureSize.height(); - } else { - textureBottom = (textureCoords.bottom() + 1) / (float)textureSize.height(); - textureTop = textureCoords.top() / (float)textureSize.height(); - } - textureLeft = textureCoords.left() / (float)textureSize.width(); - } - - if(!m_drawing) { - bindTexture(texture); - glBegin(GL_QUADS); - } - - glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top); - glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom); - glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom); - glTexCoord2f(textureRight, textureTop); glVertex2i(right, top); - - if(!m_drawing) - glEnd(); -} - -void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords) -{ - if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty()) - return; - - bool mustStopDrawing = false; - if(!m_drawing) { - bindTexture(texture); - startDrawing(); - mustStopDrawing = true; - } - - // render many repeated texture rects - Rect virtualScreenCoords(0,0,screenCoords.size()); - for(int y = 0; y <= virtualScreenCoords.height(); y += textureCoords.height()) { - for(int x = 0; x <= virtualScreenCoords.width(); x += textureCoords.width()) { - Rect partialCoords(x, y, textureCoords.size()); - Rect partialTextureCoords = textureCoords; - - // partialCoords to screenCoords bottomRight - if(partialCoords.bottom() > virtualScreenCoords.bottom()) { - partialTextureCoords.setBottom(partialTextureCoords.bottom() + - (virtualScreenCoords.bottom() - partialCoords.bottom())); - partialCoords.setBottom(virtualScreenCoords.bottom()); - } - if(partialCoords.right() > virtualScreenCoords.right()) { - partialTextureCoords.setRight(partialTextureCoords.right() + - (virtualScreenCoords.right() - partialCoords.right())); - partialCoords.setRight(virtualScreenCoords.right()); - } - - partialCoords.translate(screenCoords.topLeft()); - drawTexturedRect(partialCoords, texture, partialTextureCoords); - } - } - - if(mustStopDrawing) - stopDrawing(); -} - -void Graphics::drawFilledRect(const Rect& screenCoords) -{ - assert(!m_drawing); - - if(screenCoords.isEmpty()) - return; - - // rect correction for opengl - int right = screenCoords.right() + 1; - int bottom = screenCoords.bottom() + 1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - glVertex2i(left, top); - glVertex2i(left, bottom); - glVertex2i(right, bottom); - glVertex2i(right, top); - - glEnd(); - glEnable(GL_TEXTURE_2D); -} - - -void Graphics::drawBoundingRect(const Rect& screenCoords, - int innerLineWidth) -{ - assert(!m_drawing); - - if(screenCoords.isEmpty() || 2 * innerLineWidth > screenCoords.height()) - return; - - // rect correction for opengl - int right = screenCoords.right()+1; - int bottom = screenCoords.bottom()+1; - int top = screenCoords.top(); - int left = screenCoords.left(); - - glDisable(GL_TEXTURE_2D); - glBegin(GL_QUADS); - - // top line - glVertex2i(left, top); - glVertex2i(left, top + innerLineWidth); - glVertex2i(right, top + innerLineWidth); - glVertex2i(right, top); - - // left - glVertex2i(left, screenCoords.top() + innerLineWidth); - glVertex2i(left, bottom - innerLineWidth); - glVertex2i(left + innerLineWidth, bottom - innerLineWidth); - glVertex2i(left + innerLineWidth, screenCoords.top() + innerLineWidth); - - // bottom line - glVertex2i(left, bottom); - glVertex2i(left, bottom - innerLineWidth); - glVertex2i(right, bottom - innerLineWidth); - glVertex2i(right, bottom); - - // right line - glVertex2i(right , top + innerLineWidth); - glVertex2i(right , bottom - innerLineWidth); - glVertex2i(right - innerLineWidth, bottom - innerLineWidth); - glVertex2i(right - innerLineWidth, top + innerLineWidth); - - glEnd(); - glEnable(GL_TEXTURE_2D); -} - -void Graphics::bindColor(const Color& color) -{ - Color tmp = color; - tmp.setAlpha(std::min((uint8)m_opacity, color.a())); - glColor4ubv(tmp.rgbaPtr()); -} - -void Graphics::bindTexture(const TexturePtr& texture) -{ - glBindTexture(GL_TEXTURE_2D, texture->getId()); -} - -void Graphics::bindBlendFunc(Fw::BlendFunc blendType) -{ - switch(blendType) { - case Fw::BlendDefault: - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - break; - case Fw::BlendColorzing: - glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); - break; - case Fw::BlendParticles: - glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_ONE); - break; - } -} - -void Graphics::startDrawing() -{ - assert(!m_drawing); - glBegin(GL_QUADS); - m_drawing = true; -} - -void Graphics::stopDrawing() -{ - assert(m_drawing); - glEnd(); - m_drawing = false; } diff --git a/src/framework/graphics/graphics.h b/src/framework/graphics/graphics.h index fcc26feb..4096666b 100644 --- a/src/framework/graphics/graphics.h +++ b/src/framework/graphics/graphics.h @@ -24,64 +24,25 @@ #define GRAPHICS_H #include "declarations.h" +#include "painter.h" class Graphics { public: - /// Initialize default OpenGL states void init(); - - /// Termiante graphics void terminate(); - /// Check if a GL extension is supported bool isExtensionSupported(const char *extension); - /// Resizes OpenGL viewport void resize(const Size& size); - - /// Restore original viewport - void restoreViewport(); - - /// Called before every render void beginRender(); - - /// Called after every render void endRender(); - void bindColor(const Color& color); - void bindTexture(const TexturePtr& texture); - void bindBlendFunc(Fw::BlendFunc blendType); - - // drawing API - void drawTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords = Rect(), - bool upsideDown = false); - - void drawRepeatedTexturedRect(const Rect& screenCoords, - const TexturePtr& texture, - const Rect& textureCoords); - - void drawFilledRect(const Rect& screenCoords); - - void drawBoundingRect(const Rect& screenCoords, - int innerLineWidth = 1); - - const Size& getScreenSize() const { return m_screenSize; } - - void startDrawing(); - void stopDrawing(); - bool isDrawing() const { return m_drawing; } - - int getOpacity() const { return m_opacity; } - void setOpacity(int opacity) { m_opacity = opacity; } + const Size& getViewportSize() const { return m_viewportSize; } TexturePtr getEmptyTexture() { return m_emptyTexture; } private: - bool m_drawing; - int m_opacity; - Size m_screenSize; + Size m_viewportSize; TexturePtr m_emptyTexture; }; diff --git a/src/framework/graphics/image.cpp b/src/framework/graphics/image.cpp index 146f0016..fce2d55b 100644 --- a/src/framework/graphics/image.cpp +++ b/src/framework/graphics/image.cpp @@ -52,7 +52,13 @@ void Image::loadFromOTML(const OTMLNodePtr& imageNode) void Image::draw(const Rect& screenCoords) { - if(m_texture) { + if(!m_texture) + return; + + if(m_cachedScreenCoords != screenCoords) { + m_cachedScreenCoords = screenCoords; + m_coordsBuffer.clear(); + if(m_fixedRatio) { const Size& texSize = m_texture->getSize(); Size texCoordsSize = screenCoords.size(); @@ -63,12 +69,14 @@ void Image::draw(const Rect& screenCoords) else if(texSize.width() > texCoordsSize.width()) texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2; - g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); + m_coordsBuffer.addRect(screenCoords, Rect(texCoordsOffset, texCoordsSize)); } else { if(m_repeated) - g_graphics.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords); + m_coordsBuffer.addRepeatedRects(screenCoords, m_textureCoords); else - g_graphics.drawTexturedRect(screenCoords, m_texture, m_textureCoords); + m_coordsBuffer.addRect(screenCoords, m_textureCoords); } } + + g_painter.drawTextureCoords(m_coordsBuffer, m_texture); } diff --git a/src/framework/graphics/image.h b/src/framework/graphics/image.h index 61b884d4..ee09cf3e 100644 --- a/src/framework/graphics/image.h +++ b/src/framework/graphics/image.h @@ -24,6 +24,7 @@ #define IMAGE_H #include "declarations.h" +#include "coordsbuffer.h" #include @@ -41,6 +42,9 @@ protected: Rect m_textureCoords; bool m_fixedRatio; bool m_repeated; + + Rect m_cachedScreenCoords; + CoordsBuffer m_coordsBuffer; }; #endif diff --git a/src/framework/graphics/painter.cpp b/src/framework/graphics/painter.cpp new file mode 100644 index 00000000..1a418d4e --- /dev/null +++ b/src/framework/graphics/painter.cpp @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "painter.h" +#include "texture.h" +#include "paintershadersources.h" +#include "paintershaderprogram.h" +#include "shaderprogram.h" +#include "graphics.h" +#include "vertexarray.h" + +Painter g_painter; + +void Painter::init() +{ + setColor(Fw::white); + setOpacity(255); + setCompositionMode(CompositionMode_SourceOver); + + m_drawTexturedProgram = PainterShaderProgramPtr(new PainterShaderProgram); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + m_drawTexturedProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslTextureSrcFragmentShader); + assert(m_drawTexturedProgram->link()); + + m_drawSolidColorProgram = PainterShaderProgramPtr(new PainterShaderProgram); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader + glslPositionOnlyVertexShader); + m_drawSolidColorProgram->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader + glslSolidColorFragmentShader); + assert(m_drawSolidColorProgram->link()); +} + +void Painter::terminate() +{ + m_drawTexturedProgram.reset(); + m_drawSolidColorProgram.reset(); +} + +void Painter::updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis) +{ + // The projection matrix converts from Painter's coordinate system to GL's coordinate system + // * GL's viewport is 2x2, Painter's is width x height + // * GL has +y -> -y going from bottom -> top, Painter is the other way round + // * GL has [0,0] in the center, Painter has it in the top-left + // + // This results in the Projection matrix below, which is multiplied by the painter's + // transformation matrix, as shown below: + // + // Projection Matrix Painter Coord GL Coord + // ------------------------------------------------ --------- --------- + // | 2.0 / width | 0.0 | -1.0 | | x | | y' | + // | 0.0 | -2.0 / height | 1.0 | * | y | = | x' | + // | 0.0 | 0.0 | 0.0 | | 1 | | 0 | + // ------------------------------------------------ --------- --------- + float w = viewportSize.width(); + float h = viewportSize.height(); + if(inverseYAxis) { + m_projectionMatrix[0][0] = 2.0f/w; m_projectionMatrix[0][1] = 0.0f; m_projectionMatrix[0][2] =-1.0f; + m_projectionMatrix[1][0] = 0.0f; m_projectionMatrix[1][1] = 2.0f/h; m_projectionMatrix[1][2] =-1.0f; + m_projectionMatrix[2][0] = 0.0f; m_projectionMatrix[2][1] = 0.0f; m_projectionMatrix[2][2] = 0.0f; + } else { + m_projectionMatrix[0][0] = 2.0f/w; m_projectionMatrix[0][1] = 0.0f; m_projectionMatrix[0][2] =-1.0f; + m_projectionMatrix[1][0] = 0.0f; m_projectionMatrix[1][1] =-2.0f/h; m_projectionMatrix[1][2] = 1.0f; + m_projectionMatrix[2][0] = 0.0f; m_projectionMatrix[2][1] = 0.0f; m_projectionMatrix[2][2] = 0.0f; + } +} + +void Painter::drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode) +{ + coordsBuffer.cacheVertexArrays(); + if(coordsBuffer.getVertexCount() == 0) + return; + + program->setProjectionMatrix(m_projectionMatrix); + program->setOpacity(m_currentOpacity); + program->setColor(m_currentColor); + program->draw(coordsBuffer, drawMode); +} + +void Painter::drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture) +{ + PainterShaderProgramPtr program = m_customProgram ? m_customProgram : m_drawTexturedProgram; + program->setTexture(texture); + drawProgram(program, coordsBuffer); +} + +void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture) +{ + drawTexturedRect(dest, texture, Rect(Point(0,0), texture->getSize())); +} + +void Painter::drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest, src); + drawTextureCoords(m_coordsBuffer, texture); +} + +void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src) +{ + if(dest.isEmpty() || src.isEmpty() || !texture->getId()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRepeatedRects(dest, src); + drawTextureCoords(m_coordsBuffer, texture); +} + +void Painter::drawFilledRect(const Rect& dest) +{ + if(dest.isEmpty()) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addRect(dest); + drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram, m_coordsBuffer); +} + +void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth) +{ + if(dest.isEmpty() || innerLineWidth == 0) + return; + + m_coordsBuffer.clear(); + m_coordsBuffer.addBoudingRect(dest, innerLineWidth); + drawProgram(m_customProgram ? m_customProgram : m_drawSolidColorProgram, m_coordsBuffer); +} + +void Painter::setCustomProgram(PainterShaderProgramPtr program) +{ + m_customProgram = program; +} + +void Painter::setCompositionMode(Painter::CompositionMode compositionMode) +{ + switch(compositionMode) { + case CompositionMode_SourceOver: + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + break; + case CompositionMode_ColorizeSource: + glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA); + break; + case CompositionMode_AdditiveSource: + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + break; + } +} diff --git a/src/framework/graphics/painter.h b/src/framework/graphics/painter.h new file mode 100644 index 00000000..07b91569 --- /dev/null +++ b/src/framework/graphics/painter.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTER_H +#define PAINTER_H + +#include "declarations.h" +#include +#include "coordsbuffer.h" +#include "paintershaderprogram.h" + +class Painter +{ +public: + enum CompositionMode { + CompositionMode_SourceOver, + CompositionMode_ColorizeSource, + CompositionMode_AdditiveSource + }; + + void init(); + void terminate(); + + void updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis = false); + + void drawProgram(const PainterShaderProgramPtr& program, CoordsBuffer& coordsBuffer, PainterShaderProgram::DrawMode drawMode = PainterShaderProgram::Triangles); + void drawTextureCoords(CoordsBuffer& coordsBuffer, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture); + void drawTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src); + void drawFilledRect(const Rect& dest); + void drawBoundingRect(const Rect& dest, int innerLineWidth = 1); + + void setColor(const Color& color) { m_currentColor = color; } + Color getColor() { return m_currentColor; } + + void setOpacity(int opacity) { m_currentOpacity = opacity / 255.0f; } + int getOpacity() { return m_currentOpacity * 255.0f; } + + void setCustomProgram(PainterShaderProgramPtr program); + void releaseCustomProgram() { m_customProgram = nullptr; } + void setCompositionMode(CompositionMode compositionMode); + + GLfloat *getProjectionMatrix() { return (GLfloat*)m_projectionMatrix; } + +private: + PainterShaderProgramPtr m_drawTexturedProgram; + PainterShaderProgramPtr m_drawSolidColorProgram; + PainterShaderProgramPtr m_customProgram; + GLfloat m_projectionMatrix[3][3]; + Color m_currentColor; + GLfloat m_currentOpacity; + CoordsBuffer m_coordsBuffer; +}; + +extern Painter g_painter; + +#endif diff --git a/src/framework/graphics/paintershaderprogram.cpp b/src/framework/graphics/paintershaderprogram.cpp new file mode 100644 index 00000000..020d8a65 --- /dev/null +++ b/src/framework/graphics/paintershaderprogram.cpp @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "paintershaderprogram.h" +#include "painter.h" +#include "texture.h" +#include "texturemanager.h" +#include + +bool PainterShaderProgram::link() +{ + bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord"); + bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord"); + if(ShaderProgram::link()) { + bindUniformLocation(PROJECTION_MATRIX_UNIFORM, "projectionMatrix"); + bindUniformLocation(TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix"); + bindUniformLocation(COLOR_UNIFORM, "color"); + bindUniformLocation(OPACITY_UNIFORM, "opacity"); + bindUniformLocation(TEXTURE_UNIFORM, "texture"); + bindUniformLocation(TICKS_UNIFORM, "ticks"); + return true; + } + return false; +} + +void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3]) +{ + bind(); + setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix, true); +} + +void PainterShaderProgram::setColor(const Color& color) +{ + bind(); + setUniformValue(COLOR_UNIFORM, color); +} + +void PainterShaderProgram::setOpacity(GLfloat opacity) +{ + bind(); + setUniformValue(OPACITY_UNIFORM, opacity); +} + +void PainterShaderProgram::setUniformTexture(int location, const TexturePtr& texture, int index) +{ + if(!texture) + return; + glActiveTexture(GL_TEXTURE0 + index); + glBindTexture(GL_TEXTURE_2D, texture->getId()); + setUniformValue(location, index); +} + +void PainterShaderProgram::setTexture(const TexturePtr& texture) +{ + if(!texture) + return; + + float w = texture->getGlSize().width(); + float h = texture->getGlSize().height(); + + GLfloat textureTransformMatrix[2][2] = { + { 1.0f/w, 0.0f }, + { 0.0f, 1.0f/h } + }; + + bind(); + setUniformTexture(TEXTURE_UNIFORM, texture, 0); + setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true); +} + +void PainterShaderProgram::draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode) +{ + assert(bind()); + + setUniformValue(TICKS_UNIFORM, (GLfloat)g_clock.ticks()); + + int numVertices = coordsBuffer.getVertexCount(); + if(numVertices == 0) + return; + + bool mustDisableVertexArray = false; + if(coordsBuffer.getVertexCount() > 0) { + enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, coordsBuffer.getVertices(), 2); + mustDisableVertexArray = true; + } + + bool mustDisableTexCoordsArray = false; + if(coordsBuffer.getTextureCoords() > 0) { + enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); + setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, coordsBuffer.getTextureCoords(), 2); + mustDisableTexCoordsArray = true; + } + + glDrawArrays(drawMode, 0, numVertices); + + if(mustDisableVertexArray) + disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR); + + if(mustDisableTexCoordsArray) + disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR); + + //release(); +} + diff --git a/src/framework/graphics/paintershaderprogram.h b/src/framework/graphics/paintershaderprogram.h new file mode 100644 index 00000000..80f1e19f --- /dev/null +++ b/src/framework/graphics/paintershaderprogram.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef PAINTERSHADER_H +#define PAINTERSHADER_H + +#include "shaderprogram.h" +#include "coordsbuffer.h" + +class PainterShaderProgram : public ShaderProgram +{ + enum { + VERTEX_COORDS_ATTR = 0, + TEXTURE_COORDS_ATTR = 1, + PROJECTION_MATRIX_UNIFORM = 0, + TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1, + COLOR_UNIFORM = 2, + OPACITY_UNIFORM = 3, + TEXTURE_UNIFORM = 4, + TICKS_UNIFORM = 5 + }; +public: + enum DrawMode { + Triangles = GL_TRIANGLES, + TriangleStrip = GL_TRIANGLE_STRIP + }; + + bool link(); + + void setProjectionMatrix(GLfloat projectionMatrix[3][3]); + void setColor(const Color& color); + void setOpacity(GLfloat opacity); + void setTexture(const TexturePtr& texture); + void setUniformTexture(int location, const TexturePtr& texture, int index); + void draw(const CoordsBuffer& coordsBuffer, DrawMode drawMode = Triangles); + +private: + DrawMode m_drawMode; +}; + +#endif diff --git a/src/framework/graphics/paintershadersources.h b/src/framework/graphics/paintershadersources.h new file mode 100644 index 00000000..1e7db419 --- /dev/null +++ b/src/framework/graphics/paintershadersources.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +static int VERTEX_COORDS_ATTR = 0; +static int TEXTURE_COORDS_ATTR = 1; + +static int PROJECTION_MATRIX_UNIFORM = 0; +static int TEXTURE_TRANSFORM_MATRIX_UNIFORM = 1; +static int COLOR_UNIFORM = 2; +static int OPACITY_UNIFORM = 3; +static int TEXTURE_UNIFORM = 4; + +static const std::string glslMainVertexShader = "\n\ + highp vec4 calculatePosition();\n\ + void main() {\n\ + gl_Position = calculatePosition();\n\ + }\n"; + +static const std::string glslMainWithTexCoordsVertexShader = "\n\ + attribute highp vec2 textureCoord;\n\ + uniform highp mat2 textureTransformMatrix;\n\ + varying highp vec2 textureCoords;\n\ + highp vec4 calculatePosition();\n\ + void main()\n\ + {\n\ + gl_Position = calculatePosition();\n\ + textureCoords = textureTransformMatrix * textureCoord;\n\ + }\n"; + +static std::string glslPositionOnlyVertexShader = "\n\ + attribute highp vec2 vertexCoord;\n\ + uniform highp mat3 projectionMatrix;\n\ + highp vec4 calculatePosition() {\n\ + return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\ + }\n"; + +static const std::string glslMainFragmentShader = "\n\ + uniform lowp float opacity;\n\ + lowp vec4 calculatePixel();\n\ + void main()\n\ + {\n\ + gl_FragColor = calculatePixel() * opacity;\n\ + }\n"; + +static const std::string glslTextureSrcFragmentShader = "\n\ + varying mediump vec2 textureCoords;\n\ + uniform lowp vec4 color;\n\ + uniform sampler2D texture;\n\ + lowp vec4 calculatePixel() {\n\ + return texture2D(texture, textureCoords) * color;\n\ + }\n"; + +static const std::string glslSolidColorFragmentShader = "\n\ + uniform lowp vec4 color;\n\ + lowp vec4 calculatePixel() {\n\ + return color;\n\ + }\n"; diff --git a/src/framework/graphics/particlessystem.cpp b/src/framework/graphics/particlessystem.cpp index 9bce62c0..b4c12e61 100644 --- a/src/framework/graphics/particlessystem.cpp +++ b/src/framework/graphics/particlessystem.cpp @@ -19,19 +19,19 @@ Particle::Particle(const Rect& rect, float vx, float vy, float ax, float ay, flo Particle::~Particle() { - dump << "deleted"; + //dump << "deleted"; } void Particle::render() { - g_graphics.bindColor(m_color); + g_painter.setColor(m_color); if(!m_texture) - g_graphics.drawFilledRect(m_rect); + g_painter.drawFilledRect(m_rect); else { - g_graphics.bindBlendFunc(Fw::BlendParticles); - g_graphics.drawTexturedRect(m_rect, m_texture); - g_graphics.bindBlendFunc(Fw::BlendDefault); + g_painter.setCompositionMode(Painter::CompositionMode_AdditiveSource); + g_painter.drawTexturedRect(m_rect, m_texture); + g_painter.setCompositionMode(Painter::CompositionMode_SourceOver); } } diff --git a/src/framework/graphics/shader.cpp b/src/framework/graphics/shader.cpp new file mode 100644 index 00000000..ca24c03d --- /dev/null +++ b/src/framework/graphics/shader.cpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shader.h" +#include + +Shader::Shader(Shader::ShaderType shaderType) +{ + m_shaderType = shaderType; + switch(shaderType) { + case Vertex: + m_shaderId = glCreateShader(GL_VERTEX_SHADER); + break; + case Fragment: + m_shaderId = glCreateShader(GL_FRAGMENT_SHADER); + break; + } + + if(!m_shaderId) + logFatal("Unable to create GL shader"); +} + +Shader::~Shader() +{ + glDeleteShader(m_shaderId); +} + +bool Shader::compileSourceCode(const std::string& sourceCode) +{ +#ifndef OPENGL_ES2 + static const char *qualifierDefines = + "#define lowp\n" + "#define mediump\n" + "#define highp\n"; +#else + static const char *qualifierDefines = + "#ifndef GL_FRAGMENT_PRECISION_HIGH\n" + "#define highp mediump\n" + "#endif\n"; +#endif + + std::string code = qualifierDefines; + code.append(sourceCode); + const char *c_source = code.c_str(); + glShaderSource(m_shaderId, 1, &c_source, NULL); + glCompileShader(m_shaderId); + + int res; + glGetShaderiv(m_shaderId, GL_COMPILE_STATUS, &res); + return (res == GL_TRUE); +} + +bool Shader::compileSourceFile(const std::string& sourceFile) +{ + std::string sourceCode = g_resources.loadFile(sourceFile); + return compileSourceCode(sourceCode); +} + +std::string Shader::log() +{ + std::string infoLog; + GLint infoLogLength; + glGetShaderiv(m_shaderId, GL_INFO_LOG_LENGTH, &infoLogLength); + if(infoLogLength > 1) { + std::vector buf(infoLogLength); + glGetShaderInfoLog(m_shaderId, infoLogLength-1, NULL, &buf[0]); + infoLog = &buf[0]; + } + return infoLog; +} diff --git a/src/framework/graphics/shader.h b/src/framework/graphics/shader.h new file mode 100644 index 00000000..226fe20e --- /dev/null +++ b/src/framework/graphics/shader.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHADER_H +#define SHADER_H + +#include "declarations.h" + +class Shader +{ +public: + enum ShaderType { + Vertex, + Fragment + }; + + Shader(ShaderType shaderType); + ~Shader(); + + bool compileSourceCode(const std::string& sourceCode); + bool compileSourceFile(const std::string& sourceFile); + std::string log(); + + GLuint getShaderId() { return m_shaderId; } + ShaderType getShaderType() { return m_shaderType; } + +private: + GLuint m_shaderId; + ShaderType m_shaderType; +}; + +#endif diff --git a/src/framework/graphics/shaderprogram.cpp b/src/framework/graphics/shaderprogram.cpp new file mode 100644 index 00000000..ace96f81 --- /dev/null +++ b/src/framework/graphics/shaderprogram.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "shaderprogram.h" + +GLuint ShaderProgram::m_currentProgram = 0; + +ShaderProgram::ShaderProgram() +{ + m_linked = false; + m_programId = glCreateProgram(); + m_uniformLocations.fill(-1); + if(!m_programId) + logFatal("Unable to create GL shader program"); +} + +ShaderProgram::~ShaderProgram() +{ + glDeleteProgram(m_programId); +} + +bool ShaderProgram::addShader(const ShaderPtr& shader) { + glAttachShader(m_programId, shader->getShaderId()); + m_linked = false; + m_shaders.push_back(shader); + return true; +} + +bool ShaderProgram::addShaderFromSourceCode(Shader::ShaderType shaderType, const std::string& sourceCode) { + ShaderPtr shader(new Shader(shaderType)); + if(!shader->compileSourceCode(sourceCode)) { + logError("failed to compile shader: ", shader->log()); + return false; + } + return addShader(shader); +} + +bool ShaderProgram::addShaderFromSourceFile(Shader::ShaderType shaderType, const std::string& sourceFile) { + ShaderPtr shader(new Shader(shaderType)); + if(!shader->compileSourceFile(sourceFile)) { + logError("failed to compile shader: ", shader->log()); + return false; + } + return addShader(shader); +} + +void ShaderProgram::removeShader(const ShaderPtr& shader) +{ + auto it = std::find(m_shaders.begin(), m_shaders.end(), shader); + if(it == m_shaders.end()) + return; + + glDetachShader(m_programId, shader->getShaderId()); + m_shaders.erase(it); + m_linked = false; +} + +void ShaderProgram::removeAllShaders() +{ + while(!m_shaders.empty()) + removeShader(m_shaders.front()); +} + +bool ShaderProgram::link() +{ + if(m_linked) + return true; + + glLinkProgram(m_programId); + + GLint value; + glGetProgramiv(m_programId, GL_LINK_STATUS, &value); + m_linked = (value != GL_FALSE); + + if(!m_linked) + logTraceWarning(log()); + return m_linked; +} + +bool ShaderProgram::bind() +{ + if(m_currentProgram != m_programId) { + if(!m_linked && !link()) + return false; + glUseProgram(m_programId); + m_currentProgram = m_programId; + } + return true; +} + +void ShaderProgram::release() +{ + m_currentProgram = 0; + glUseProgram(0); +} + +std::string ShaderProgram::log() +{ + std::string infoLog; + GLint infoLogLength; + glGetProgramiv(m_programId, GL_INFO_LOG_LENGTH, &infoLogLength); + if(infoLogLength > 1) { + std::vector buf(infoLogLength); + glGetShaderInfoLog(m_programId, infoLogLength-1, NULL, &buf[0]); + infoLog = &buf[0]; + } + return infoLog; +} + +int ShaderProgram::getAttributeLocation(const char* name) +{ + return glGetAttribLocation(m_programId, name); +} + +void ShaderProgram::bindAttributeLocation(int location, const char* name) +{ + return glBindAttribLocation(m_programId, location, name); +} + +void ShaderProgram::bindUniformLocation(int location, const char* name) +{ + assert(m_linked); + assert(location >= 0 && location < MAX_UNIFORM_LOCATIONS); + m_uniformLocations[location] = glGetUniformLocation(m_programId, name); +} diff --git a/src/framework/graphics/shaderprogram.h b/src/framework/graphics/shaderprogram.h new file mode 100644 index 00000000..f05cd226 --- /dev/null +++ b/src/framework/graphics/shaderprogram.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef SHADERPROGRAM_H +#define SHADERPROGRAM_H + +#include "shader.h" + +class ShaderProgram +{ + enum { + MAX_UNIFORM_LOCATIONS = 30 + }; +public: + ShaderProgram(); + ~ShaderProgram(); + + bool addShader(const ShaderPtr& shader); + bool addShaderFromSourceCode(Shader::ShaderType shaderType, const std::string& sourceCode); + bool addShaderFromSourceFile(Shader::ShaderType shaderType, const std::string& sourceFile); + void removeShader(const ShaderPtr& shader); + void removeAllShaders(); + virtual bool link(); + bool bind(); + void release(); + std::string log(); + + void disableAttributeArray(int location) { glDisableVertexAttribArray(location); } + void enableAttributeArray(int location) { glEnableVertexAttribArray(location); } + void disableAttributeArray(const char *name) { glDisableVertexAttribArray(getAttributeLocation(name)); } + void enableAttributeArray(const char *name) { glEnableVertexAttribArray(getAttributeLocation(name)); } + + int getAttributeLocation(const char *name); + void bindAttributeLocation(int location, const char *name); + void bindUniformLocation(int location, const char *name); + + void setAttributeArray(int location, const GLfloat *values, int size, int stride = 0) { glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE, stride, values); } + void setAttributeValue(int location, GLfloat value) { glVertexAttrib1f(location, value); } + void setAttributeValue(int location, GLfloat x, GLfloat y) { glVertexAttrib2f(location, x, y); } + void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(location, x, y, z); } + void setAttributeArray(const char *name, const GLfloat *values, int size, int stride = 0) { glVertexAttribPointer(getAttributeLocation(name), size, GL_FLOAT, GL_FALSE, stride, values); } + void setAttributeValue(const char *name, GLfloat value) { glVertexAttrib1f(getAttributeLocation(name), value); } + void setAttributeValue(const char *name, GLfloat x, GLfloat y) { glVertexAttrib2f(getAttributeLocation(name), x, y); } + void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glVertexAttrib3f(getAttributeLocation(name), x, y, z); } + + void setUniformValue(int location, const Color& color) { glUniform4f(m_uniformLocations[location], color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); } + void setUniformValue(int location, GLint value) { glUniform1i(m_uniformLocations[location], value); } + void setUniformValue(int location, GLfloat value) { glUniform1f(m_uniformLocations[location], value); } + void setUniformValue(int location, GLfloat x, GLfloat y) { glUniform2f(m_uniformLocations[location], x, y); } + void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z) { glUniform3f(m_uniformLocations[location], x, y, z); } + void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(m_uniformLocations[location], x, y, z, w); } + void setUniformValue(int location, GLfloat mat2[2][2], bool transpose) { glUniformMatrix2fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); } + void setUniformValue(int location, GLfloat mat3[3][3], bool transpose) { glUniformMatrix3fv(m_uniformLocations[location], 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); } + void setUniformValue(const char *name, const Color& color) { glUniform4f(glGetUniformLocation(m_programId, name), color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f, color.a() / 255.0f); } + void setUniformValue(const char *name, GLint value) { glUniform1i(glGetUniformLocation(m_programId, name), value); } + void setUniformValue(const char *name, GLfloat value) { glUniform1f(glGetUniformLocation(m_programId, name), value); } + void setUniformValue(const char *name, GLfloat x, GLfloat y) { glUniform2f(glGetUniformLocation(m_programId, name), x, y); } + void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z) { glUniform3f(glGetUniformLocation(m_programId, name), x, y, z); } + void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w) { glUniform4f(glGetUniformLocation(m_programId, name), x, y, z, w); } + void setUniformValue(const char *name, GLfloat mat2[2][2], bool transpose = false) { glUniformMatrix2fv(glGetUniformLocation(m_programId, name), 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat2); } + void setUniformValue(const char *name, GLfloat mat3[3][3], bool transpose = false) { glUniformMatrix3fv(glGetUniformLocation(m_programId, name), 1, transpose ? GL_TRUE : GL_FALSE, (GLfloat *)mat3); } + + // Point, PointF, Color, Size, SizeF, + bool isLinked() { return m_linked; } + GLuint getProgramId() { return m_programId; } + ShaderList getShaders() { return m_shaders; } + +private: + bool m_linked; + GLuint m_programId; + static GLuint m_currentProgram; + ShaderList m_shaders; + std::array m_uniformLocations; +}; + +#endif diff --git a/src/framework/graphics/texture.cpp b/src/framework/graphics/texture.cpp index ef3a8de2..2ce5dc7c 100644 --- a/src/framework/graphics/texture.cpp +++ b/src/framework/graphics/texture.cpp @@ -36,7 +36,6 @@ Texture::Texture(int width, int height, int channels, uchar *pixels) Texture::~Texture() { - assert(!g_graphics.isDrawing()); // free texture from gl memory if(m_textureId > 0) glDeleteTextures(1, &m_textureId); @@ -44,9 +43,7 @@ Texture::~Texture() uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height) { - assert(!g_graphics.isDrawing()); - - m_size.setSize(width, height); + m_size.resize(width, height); // gets max texture size supported by the driver static GLint maxTexSize = -1; @@ -70,7 +67,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int std::vector tmp; // old opengl drivers only accept power of two dimensions - //if(!g_graphics.isExtensionSupported("GL_ARB_texture_non_power_of_two")) { + //if(!g_painter.isExtensionSupported("GL_ARB_texture_non_power_of_two")) { int glWidth = 1; while(glWidth < width) glWidth = glWidth << 1; @@ -88,7 +85,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int pixels = &tmp[0]; } - m_glSize.setSize(glWidth, glHeight); + m_glSize.resize(glWidth, glHeight); //} else // m_glSize = m_size; @@ -110,7 +107,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int } // load pixels into gl memory - glTexImage2D(GL_TEXTURE_2D, 0, channels, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels); // disable texture border glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); @@ -119,7 +116,6 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int // nearest filtering (non smooth) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - return id; } diff --git a/src/framework/graphics/texture.h b/src/framework/graphics/texture.h index e0e88795..0fe4cd73 100644 --- a/src/framework/graphics/texture.h +++ b/src/framework/graphics/texture.h @@ -37,22 +37,22 @@ public: virtual void enableBilinearFilter(); /// Get OpenGL texture id - uint getId() const { return m_textureId; } + GLuint getId() { return m_textureId; } /// Copy pixels from OpenGL texture std::vector getPixels(); - int getWidth() const { return m_size.width(); } - int getHeight() const { return m_size.height(); } - const Size& getSize() const { return m_size; } - const Size& getGlSize() const { return m_glSize; } + int getWidth() { return m_size.width(); } + int getHeight() { return m_size.height(); } + const Size& getSize() { return m_size; } + const Size& getGlSize() { return m_glSize; } bool isEmpty() const { return m_textureId == 0; } protected: - uint internalLoadGLTexture(uchar* pixels, int channels, int w, int h); + GLuint internalLoadGLTexture(uchar* pixels, int channels, int w, int h); - uint m_textureId; + GLuint m_textureId; Size m_size; Size m_glSize; }; diff --git a/src/framework/graphics/textureglyphcache.cpp b/src/framework/graphics/textureglyphcache.cpp new file mode 100644 index 00000000..6a5c7d47 --- /dev/null +++ b/src/framework/graphics/textureglyphcache.cpp @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "textureglyphcache.h" + diff --git a/src/framework/graphics/textureglyphcache.h b/src/framework/graphics/textureglyphcache.h new file mode 100644 index 00000000..15833249 --- /dev/null +++ b/src/framework/graphics/textureglyphcache.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef TEXTUREGLYPHCACHE_H +#define TEXTUREGLYPHCACHE_H + +class TextureGlyphCache +{ +}; + +#endif diff --git a/src/framework/graphics/vertexarray.h b/src/framework/graphics/vertexarray.h new file mode 100644 index 00000000..b21cdf82 --- /dev/null +++ b/src/framework/graphics/vertexarray.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef VERTEXARRAY_H +#define VERTEXARRAY_H + +#include "declarations.h" +#include + +class VertexArray +{ +public: + inline void addVertex(GLfloat x, GLfloat y) { m_buffer << x << y; } + inline void addRect(const Rect& rect) { + GLfloat top = rect.top(); + GLfloat right = rect.right()+1; + GLfloat bottom = rect.bottom()+1; + GLfloat left = rect.left(); + + addVertex(left, top); + addVertex(right, top); + addVertex(left, bottom); + addVertex(left, bottom); + addVertex(right, top); + addVertex(right, bottom); + } + + inline void addQuad(const Rect& rect) { + GLfloat top = rect.top(); + GLfloat right = rect.right()+1; + GLfloat bottom = rect.bottom()+1; + GLfloat left = rect.left(); + + addVertex(left, top); + addVertex(right, top); + addVertex(left, bottom); + addVertex(right, bottom); + } + + void clear() { m_buffer.reset(); } + GLfloat *vertices() const { return m_buffer.data(); } + int vertexCount() const { return m_buffer.size() / 2; } + +private: + DataBuffer m_buffer; +}; + +#endif diff --git a/src/framework/luafunctions.cpp b/src/framework/luafunctions.cpp index 8c57cf3b..c9aad99b 100644 --- a/src/framework/luafunctions.cpp +++ b/src/framework/luafunctions.cpp @@ -36,73 +36,110 @@ void Application::registerLuaFunctions() // UIWidget g_lua.registerClass(); g_lua.bindClassStaticFunction("create", &UIWidget::create); - 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("isExplicitlyVisible", &UIWidget::isExplicitlyVisible); + g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); 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("getSize", &UIWidget::getSize); - g_lua.bindClassMemberFunction("setSize", &UIWidget::resize); - g_lua.bindClassMemberFunction("getPosition", &UIWidget::getPosition); - g_lua.bindClassMemberFunction("getX", &UIWidget::getX); - g_lua.bindClassMemberFunction("getY", &UIWidget::getY); - g_lua.bindClassMemberFunction("moveTo", &UIWidget::moveTo); - g_lua.bindClassMemberFunction("moveChildToIndex", &UIWidget::moveChildToIndex); - 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("setEnabled", &UIWidget::setEnabled); + g_lua.bindClassMemberFunction("setPressed", &UIWidget::setPressed); + g_lua.bindClassMemberFunction("setId", &UIWidget::setId); + g_lua.bindClassMemberFunction("setFocusable", &UIWidget::setFocusable); + g_lua.bindClassMemberFunction("setPhantom", &UIWidget::setPhantom); g_lua.bindClassMemberFunction("setStyle", &UIWidget::setStyle); - g_lua.bindClassMemberFunction("applyStyle", &UIWidget::applyStyle); - g_lua.bindClassMemberFunction("getStyle", &UIWidget::getStyle); - g_lua.bindClassMemberFunction("getMarginTop", &UIWidget::getMarginTop); + g_lua.bindClassMemberFunction("setStyleFromNode", &UIWidget::setStyleFromNode); + //g_lua.bindClassMemberFunction("setLayout", &UIWidget::setLayout); + g_lua.bindClassMemberFunction("setParent", &UIWidget::setParent); + g_lua.bindClassMemberFunction("setRect", &UIWidget::setRect); + g_lua.bindClassMemberFunction("setX", &UIWidget::setX); + g_lua.bindClassMemberFunction("setY", &UIWidget::setY); + g_lua.bindClassMemberFunction("setWidth", &UIWidget::setWidth); + g_lua.bindClassMemberFunction("setHeight", &UIWidget::setHeight); + //g_lua.bindClassMemberFunction("setImage", &UIWidget::setImage); + //g_lua.bindClassMemberFunction("setFont", &UIWidget::setFont); + g_lua.bindClassMemberFunction("setOpacity", &UIWidget::setOpacity); + g_lua.bindClassMemberFunction("setBackgroundColor", &UIWidget::setBackgroundColor); + g_lua.bindClassMemberFunction("setForegroundColor", &UIWidget::setForegroundColor); 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("isVisible", &UIWidget::isVisible); - g_lua.bindClassMemberFunction("isHidden", &UIWidget::isHidden); - g_lua.bindClassMemberFunction("isHovered", &UIWidget::isHovered); - g_lua.bindClassMemberFunction("isFocused", &UIWidget::isFocused); - g_lua.bindClassMemberFunction("isPressed", &UIWidget::isPressed); - g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); - g_lua.bindClassMemberFunction("isDisabled", &UIWidget::isDisabled); - g_lua.bindClassMemberFunction("isActive", &UIWidget::isActive); + g_lua.bindClassMemberFunction("setMarginBottom", &UIWidget::setMarginBottom); + g_lua.bindClassMemberFunction("setMarginLeft", &UIWidget::setMarginLeft); + g_lua.bindClassMemberFunction("setSizeFixed", &UIWidget::setSizeFixed); + g_lua.bindClassMemberFunction("setLastFocusReason", &UIWidget::setLastFocusReason); + g_lua.bindClassMemberFunction("resize", &UIWidget::resize); + g_lua.bindClassMemberFunction("moveTo", &UIWidget::moveTo); g_lua.bindClassMemberFunction("hide", &UIWidget::hide); g_lua.bindClassMemberFunction("show", &UIWidget::show); + g_lua.bindClassMemberFunction("disable", &UIWidget::disable); + g_lua.bindClassMemberFunction("enable", &UIWidget::enable); g_lua.bindClassMemberFunction("lock", &UIWidget::lock); g_lua.bindClassMemberFunction("unlock", &UIWidget::unlock); g_lua.bindClassMemberFunction("focus", &UIWidget::focus); - g_lua.bindClassMemberFunction("getChildren", &UIWidget::getChildren); - g_lua.bindClassMemberFunction("recursiveGetChildById", &UIWidget::recursiveGetChildById); - g_lua.bindClassMemberFunction("getChildById", &UIWidget::getChildById); - g_lua.bindClassMemberFunction("getChildByIndex", &UIWidget::getChildByIndex); + g_lua.bindClassMemberFunction("isActive", &UIWidget::isActive); + g_lua.bindClassMemberFunction("isEnabled", &UIWidget::isEnabled); + g_lua.bindClassMemberFunction("isDisabled", &UIWidget::isDisabled); + g_lua.bindClassMemberFunction("isFocused", &UIWidget::isFocused); + g_lua.bindClassMemberFunction("isHovered", &UIWidget::isHovered); + g_lua.bindClassMemberFunction("isPressed", &UIWidget::isPressed); + g_lua.bindClassMemberFunction("isVisible", &UIWidget::isVisible); + g_lua.bindClassMemberFunction("isHidden", &UIWidget::isHidden); + g_lua.bindClassMemberFunction("isExplicitlyEnabled", &UIWidget::isExplicitlyEnabled); + g_lua.bindClassMemberFunction("isExplicitlyVisible", &UIWidget::isExplicitlyVisible); + g_lua.bindClassMemberFunction("isFocusable", &UIWidget::isFocusable); + g_lua.bindClassMemberFunction("isPhantom", &UIWidget::isPhantom); + g_lua.bindClassMemberFunction("isSizeFixed", &UIWidget::isSizeFixed); + g_lua.bindClassMemberFunction("hasChildren", &UIWidget::hasChildren); + g_lua.bindClassMemberFunction("hasChild", &UIWidget::hasChild); + g_lua.bindClassMemberFunction("getId", &UIWidget::getId); g_lua.bindClassMemberFunction("getChildCount", &UIWidget::getChildCount); + //g_lua.bindClassMemberFunction("getLayout", &UIWidget::getLayout); + g_lua.bindClassMemberFunction("getParent", &UIWidget::getParent); + g_lua.bindClassMemberFunction("getRootParent", &UIWidget::getRootParent); + g_lua.bindClassMemberFunction("getPosition", &UIWidget::getPosition); + g_lua.bindClassMemberFunction("getSize", &UIWidget::getSize); + g_lua.bindClassMemberFunction("getRect", &UIWidget::getRect); + g_lua.bindClassMemberFunction("getX", &UIWidget::getX); + g_lua.bindClassMemberFunction("getY", &UIWidget::getY); + g_lua.bindClassMemberFunction("getWidth", &UIWidget::getWidth); + g_lua.bindClassMemberFunction("getHeight", &UIWidget::getHeight); + //g_lua.bindClassMemberFunction("getImage", &UIWidget::getImage); + //g_lua.bindClassMemberFunction("getFont", &UIWidget::getFont); + g_lua.bindClassMemberFunction("getForegroundColor", &UIWidget::getForegroundColor); + g_lua.bindClassMemberFunction("getBackgroundColor", &UIWidget::getBackgroundColor); + g_lua.bindClassMemberFunction("getOpacity", &UIWidget::getOpacity); + g_lua.bindClassMemberFunction("getMarginTop", &UIWidget::getMarginTop); + g_lua.bindClassMemberFunction("getMarginRight", &UIWidget::getMarginRight); + g_lua.bindClassMemberFunction("getMarginBottom", &UIWidget::getMarginBottom); + g_lua.bindClassMemberFunction("getMarginLeft", &UIWidget::getMarginLeft); + g_lua.bindClassMemberFunction("getLastFocusReason", &UIWidget::getLastFocusReason); + g_lua.bindClassMemberFunction("getStyle", &UIWidget::getStyle); + g_lua.bindClassMemberFunction("getChildren", &UIWidget::getChildren); g_lua.bindClassMemberFunction("getFocusedChild", &UIWidget::getFocusedChild); + g_lua.bindClassMemberFunction("getChildAfter", &UIWidget::getChildAfter); + g_lua.bindClassMemberFunction("getChildBefore", &UIWidget::getChildBefore); + g_lua.bindClassMemberFunction("getChildById", &UIWidget::getChildById); + g_lua.bindClassMemberFunction("getChildByPos", &UIWidget::getChildByPos); + g_lua.bindClassMemberFunction("getChildByIndex", &UIWidget::getChildByIndex); + g_lua.bindClassMemberFunction("recursiveGetChildById", &UIWidget::recursiveGetChildById); + g_lua.bindClassMemberFunction("recursiveGetChildByPos", &UIWidget::recursiveGetChildByPos); + g_lua.bindClassMemberFunction("backwardsGetWidgetById", &UIWidget::backwardsGetWidgetById); + g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); g_lua.bindClassMemberFunction("insertChild", &UIWidget::insertChild); g_lua.bindClassMemberFunction("removeChild", &UIWidget::removeChild); - g_lua.bindClassMemberFunction("hasChild", &UIWidget::hasChild); - g_lua.bindClassMemberFunction("addChild", &UIWidget::addChild); g_lua.bindClassMemberFunction("focusChild", &UIWidget::focusChild); g_lua.bindClassMemberFunction("focusNextChild", &UIWidget::focusNextChild); g_lua.bindClassMemberFunction("focusPreviousChild", &UIWidget::focusPreviousChild); + g_lua.bindClassMemberFunction("moveChildToTop", &UIWidget::moveChildToTop); + g_lua.bindClassMemberFunction("moveChildToIndex", &UIWidget::moveChildToIndex); g_lua.bindClassMemberFunction("lockChild", &UIWidget::lockChild); g_lua.bindClassMemberFunction("unlockChild", &UIWidget::unlockChild); - g_lua.bindClassMemberFunction("updateLayout", &UIWidget::updateLayout); + g_lua.bindClassMemberFunction("isChildLocked", &UIWidget::isChildLocked); + g_lua.bindClassMemberFunction("getChildIndex", &UIWidget::getChildIndex); g_lua.bindClassMemberFunction("updateParentLayout", &UIWidget::updateParentLayout); - g_lua.bindClassMemberFunction("destroy", &UIWidget::destroy); + g_lua.bindClassMemberFunction("updateLayout", &UIWidget::updateLayout); + g_lua.bindClassMemberFunction("updateStates", &UIWidget::updateStates); + g_lua.bindClassMemberFunction("updateState", &UIWidget::updateState); + g_lua.bindClassMemberFunction("setState", &UIWidget::setState); + g_lua.bindClassMemberFunction("hasState", &UIWidget::hasState); + g_lua.bindClassMemberFunction("updateStyle", &UIWidget::updateStyle); + g_lua.bindClassMemberFunction("applyStyle", &UIWidget::applyStyle); // UILabel g_lua.registerClass(); @@ -175,12 +212,27 @@ void Application::registerLuaFunctions() g_lua.bindClassStaticFunction("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger)); g_lua.bindClassStaticFunction("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1)); + // Font + + /* + // FontManager + g_lua.registerStaticClass("g_fonts"); + g_lua.bindClassStaticFunction("g_fonts", "releaseFonts", std::bind(&FontManager::releaseFonts, &g_fonts)); + g_lua.bindClassStaticFunction("g_fonts", "importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "fontExists", std::bind(&FontManager::fontExists, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "getFont", std::bind(&FontManager::getFont, &g_fonts, _1)); + g_lua.bindClassStaticFunction("g_fonts", "getDefaultFont", std::bind(&FontManager::getDefaultFont, &g_fonts)); + g_lua.bindClassStaticFunction("g_fonts", "setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1)); + */ + + g_lua.registerStaticClass("g_dispatcher"); + g_lua.bindClassStaticFunction("g_dispatcher", "addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, _2)); + g_lua.bindClassStaticFunction("g_dispatcher", "scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2)); + // global functions 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("setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1)); g_lua.bindGlobalFunction("loadUI", std::bind(&UIManager::loadUI, &g_ui, _1, _2)); g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui)); - g_lua.bindGlobalFunction("addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, false)); - g_lua.bindGlobalFunction("scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2)); } diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index eeab1bf4..5e36c4a0 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -340,7 +340,7 @@ void X11Window::internalChooseGLVisual() m_rootWindow = RootWindow(m_display, m_visual->screen); #else static int attrList[] = { - EGL_BUFFER_SIZE, 16, + //EGL_BUFFER_SIZE, 24, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_NONE }; diff --git a/src/framework/ui/uibutton.cpp b/src/framework/ui/uibutton.cpp index a8650f8b..da42d0cb 100644 --- a/src/framework/ui/uibutton.cpp +++ b/src/framework/ui/uibutton.cpp @@ -40,9 +40,9 @@ void UIButton::render() if(m_icon) { Rect iconRect; - iconRect.setSize(m_icon->getSize()); + iconRect.resize(m_icon->getSize()); iconRect.moveCenter(m_rect.center()); - g_graphics.drawTexturedRect(iconRect, m_icon); + g_painter.drawTexturedRect(iconRect, m_icon); } Rect textRect = m_rect; diff --git a/src/framework/ui/uicheckbox.cpp b/src/framework/ui/uicheckbox.cpp index 5dc7962c..444414c2 100644 --- a/src/framework/ui/uicheckbox.cpp +++ b/src/framework/ui/uicheckbox.cpp @@ -38,10 +38,10 @@ void UICheckBox::render() { if(m_image) { Rect boxRect; - boxRect.setSize(m_boxSize); + boxRect.resize(m_boxSize); boxRect.moveLeft(m_rect.left()); boxRect.moveVerticalCenter(m_rect.verticalCenter()); - g_graphics.bindColor(m_backgroundColor); + g_painter.setColor(m_backgroundColor); m_image->draw(boxRect); } diff --git a/src/framework/ui/uilineedit.cpp b/src/framework/ui/uilineedit.cpp index 91df18e9..31ea118d 100644 --- a/src/framework/ui/uilineedit.cpp +++ b/src/framework/ui/uilineedit.cpp @@ -47,9 +47,9 @@ void UILineEdit::render() int textLength = m_text.length(); const TexturePtr& texture = m_font->getTexture(); - g_graphics.bindColor(m_foregroundColor); + g_painter.setColor(m_foregroundColor); for(int i=0;i= 0) { @@ -63,7 +63,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); + g_painter.drawFilledRect(cursorRect); } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) { m_cursorTicks = g_clock.ticks(); } diff --git a/src/framework/ui/uimanager.cpp b/src/framework/ui/uimanager.cpp index 6a8b3ada..344302c8 100644 --- a/src/framework/ui/uimanager.cpp +++ b/src/framework/ui/uimanager.cpp @@ -25,6 +25,7 @@ #include #include +#include UIManager g_ui; @@ -33,7 +34,7 @@ void UIManager::init() // creates root widget m_rootWidget = UIWidget::create(); m_rootWidget->setId("root"); - m_rootWidget->resize(g_graphics.getScreenSize()); + m_rootWidget->resize(g_window.getSize()); } void UIManager::terminate() @@ -50,7 +51,7 @@ void UIManager::render() void UIManager::resize(const Size& size) { - m_rootWidget->resize(g_graphics.getScreenSize()); + m_rootWidget->resize(g_window.getSize()); } void UIManager::inputEvent(const InputEvent& event) @@ -174,12 +175,15 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const U if(parent) parent->addChild(widget); - widget->setStyleFromNode(styleNode); + if(widget) { + widget->setStyleFromNode(styleNode); - for(const OTMLNodePtr& childNode : widgetNode->children()) { - if(!childNode->isUnique()) - loadWidgetFromOTML(childNode, widget); - } + for(const OTMLNodePtr& childNode : widgetNode->children()) { + if(!childNode->isUnique()) + loadWidgetFromOTML(childNode, widget); + } + } else + logError("Unable to create widget of type '", widgetType, "'"); return widget; } diff --git a/src/framework/ui/uiprogressbar.cpp b/src/framework/ui/uiprogressbar.cpp index 12013a1c..27ba173a 100644 --- a/src/framework/ui/uiprogressbar.cpp +++ b/src/framework/ui/uiprogressbar.cpp @@ -35,14 +35,14 @@ void UIProgressBar::render() { UIWidget::render(); - g_graphics.bindColor(m_foregroundColor); - g_graphics.drawBoundingRect(m_rect, 1); + g_painter.setColor(m_foregroundColor); + g_painter.drawBoundingRect(m_rect, 1); Rect fillRect = m_rect.expanded(-1); fillRect.setWidth(fillRect.width() * m_percent / 100.0); - g_graphics.bindColor(m_backgroundColor); - g_graphics.drawFilledRect(fillRect); + g_painter.setColor(m_backgroundColor); + g_painter.drawFilledRect(fillRect); } void UIProgressBar::setPercent(double percent) diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 53dfe14d..96d13480 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -69,7 +69,7 @@ void UIWidget::renderSelf() { // draw background if(m_image) { - g_graphics.bindColor(m_backgroundColor); + g_painter.setColor(m_backgroundColor); m_image->draw(m_rect); } } @@ -81,20 +81,20 @@ void UIWidget::renderChildren() // render only visible children with a valid rect inside our rect if(child->isExplicitlyVisible() && child->getRect().isValid() && child->getRect().intersects(m_rect)) { // store current graphics opacity - int oldOpacity = g_graphics.getOpacity(); + int oldOpacity = g_painter.getOpacity(); // decrease to self opacity if(child->getOpacity() < oldOpacity) - g_graphics.setOpacity(child->getOpacity()); + g_painter.setOpacity(child->getOpacity()); child->render(); // debug draw box - //g_graphics.bindColor(Fw::green); - //g_graphics.drawBoundingRect(child->getRect()); + //g_painter.setColor(Fw::green); + //g_painter.drawBoundingRect(child->getRect()); //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red); - g_graphics.setOpacity(oldOpacity); + g_painter.setOpacity(oldOpacity); } } } diff --git a/src/framework/util/databuffer.h b/src/framework/util/databuffer.h new file mode 100644 index 00000000..56b88a44 --- /dev/null +++ b/src/framework/util/databuffer.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef DATABUFFER_H +#define DATABUFFER_H + +template +class DataBuffer +{ +public: + DataBuffer(int res = 64) { + m_capacity = res; + m_buffer = new T[m_capacity]; + m_size = 0; + } + ~DataBuffer() { delete[] m_buffer; } + + inline void reset() { m_size = 0; } + inline bool isEmpty() const { return m_size == 0; } + + inline int size() const { return m_size; } + inline T *data() const { return m_buffer; } + + inline const T& at(int i) const { return m_buffer[i]; } + inline const T& last() const { return m_buffer[m_size-1]; } + inline const T& first() const { return m_buffer[0]; } + inline const T& operator[](int i) const { return m_buffer[i]; } + inline T& operator[](int i) { return m_buffer[i]; } + + inline void add(const T &t) { + if(m_size >= m_capacity) { + m_capacity *= 2; + T *buffer = new T[m_capacity]; + for(int i=0;i &p) { x1 = p.x; y2 = p.y; } void setWidth(T width) { x2 = x1 + width - 1; } void setHeight(T height) { y2 = y1 + height- 1; } - void setSize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } - void setSize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } + void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } + void resize(const TSize& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } void setRect(T x, T y, T width, T height) { x1 = x; y1 = y; x2 = (x + width - 1); y2 = (y + height - 1); } void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; } diff --git a/src/framework/util/size.h b/src/framework/util/size.h index f76204f5..9b373eee 100644 --- a/src/framework/util/size.h +++ b/src/framework/util/size.h @@ -43,7 +43,7 @@ public: int width() const { return wd; } int height() const { return ht; } - void setSize(T w, T h) { wd = w; ht = h; } + void resize(T w, T h) { wd = w; ht = h; } void setWidth(T w) { wd = w; } void setHeight(T h) { ht = h; } @@ -115,7 +115,7 @@ std::istream& operator>>(std::istream& in, TSize& size) { T w, h; in >> w >> h; - size.setSize(w, h); + size.resize(w, h); return in; } diff --git a/src/framework/util/tools.h b/src/framework/util/tools.h index 56a5fb1a..8f579303 100644 --- a/src/framework/util/tools.h +++ b/src/framework/util/tools.h @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "types.h" #include "exception.h" @@ -258,6 +260,16 @@ inline std::string ip2str(uint32 ip) { return std::string(host); } +template +std::vector split(const std::string& str, const std::string& separators = " ") { + std::vector splitted; + boost::split(splitted, str, boost::is_any_of(std::string(separators))); + std::vector results(splitted.size()); + for(uint i=0;i(splitted[i]); + return results; +} + template void throwException(const T&... args) { throw Exception(Fw::mkstr(args...)); diff --git a/src/main.cpp b/src/main.cpp index 982cf3a2..53a1a48c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,9 +25,9 @@ int main(int argc, const char* argv[]) { std::vector args(argv, argv + argc); - OTClient otclient; - otclient.init(args); - otclient.run(); - otclient.terminate(); + OTClient app; + app.init(args); + app.run(); + app.terminate(); return 0; } diff --git a/src/otclient/const.h b/src/otclient/const.h index 554f65a2..150d209e 100644 --- a/src/otclient/const.h +++ b/src/otclient/const.h @@ -250,14 +250,6 @@ namespace Otc ClientGetObjectInfo = 243 }; - enum SpriteMask { - SpriteRedMask = 0, - SpriteGreenMask, - SpriteBlueMask, - SpriteYellowMask, - SpriteNoMask = 255 - }; - enum InventorySlots { InventorySlotHead = 1, InventorySlotNecklace, diff --git a/src/otclient/core/creature.cpp b/src/otclient/core/creature.cpp index 35f11bd2..08bf079e 100644 --- a/src/otclient/core/creature.cpp +++ b/src/otclient/core/creature.cpp @@ -31,6 +31,10 @@ #include #include +#include +#include +#include "spritemanager.h" + Creature::Creature() : Thing() { m_healthPercent = 0; @@ -43,12 +47,31 @@ Creature::Creature() : Thing() m_informationFont = g_fonts.getFont("verdana-11px-rounded"); } +PainterShaderProgramPtr outfitProgram; +int HEAD_COLOR_UNIFORM = 10; +int BODY_COLOR_UNIFORM = 11; +int LEGS_COLOR_UNIFORM = 12; +int FEET_COLOR_UNIFORM = 13; +int MASK_TEXTURE_UNIFORM = 14; + void Creature::draw(const Point& p) { // TODO: activate on attack, follow, discover how 'attacked' works if(m_showSquareColor) { - g_graphics.bindColor(Outfit::getColor(m_squareColor)); - g_graphics.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); + g_painter.setColor(Outfit::getColor(m_squareColor)); + g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); + } + + if(!outfitProgram) { + outfitProgram = PainterShaderProgramPtr(new PainterShaderProgram); + outfitProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + outfitProgram->addShaderFromSourceFile(Shader::Fragment, "/outfit.frag"); + assert(outfitProgram->link()); + outfitProgram->bindUniformLocation(HEAD_COLOR_UNIFORM, "headColor"); + outfitProgram->bindUniformLocation(BODY_COLOR_UNIFORM, "bodyColor"); + outfitProgram->bindUniformLocation(LEGS_COLOR_UNIFORM, "legsColor"); + outfitProgram->bindUniformLocation(FEET_COLOR_UNIFORM, "feetColor"); + outfitProgram->bindUniformLocation(MASK_TEXTURE_UNIFORM, "maskTexture"); } // Render creature @@ -58,35 +81,52 @@ void Creature::draw(const Point& p) if(m_yPattern > 0 && !(m_outfit.getAddons() & (1 << (m_yPattern-1)))) continue; - // draw white item - g_graphics.bindColor(Fw::white); - internalDraw(p + m_walkOffset, 0); + g_painter.setCustomProgram(outfitProgram); - // draw mask if exists - if(m_type->dimensions[ThingType::Layers] > 1) { - // switch to blend color mode - g_graphics.bindBlendFunc(Fw::BlendColorzing); + outfitProgram->bind(); + outfitProgram->setUniformValue(HEAD_COLOR_UNIFORM, m_outfit.getHeadColor()); + outfitProgram->setUniformValue(BODY_COLOR_UNIFORM, m_outfit.getBodyColor()); + outfitProgram->setUniformValue(LEGS_COLOR_UNIFORM, m_outfit.getLegsColor()); + outfitProgram->setUniformValue(FEET_COLOR_UNIFORM, m_outfit.getFeetColor()); - // head - g_graphics.bindColor(m_outfit.getHeadColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask); + for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { + for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { + int sprIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) + * m_type->dimensions[ThingType::PatternZ] + m_zPattern) + * m_type->dimensions[ThingType::PatternY] + m_yPattern) + * m_type->dimensions[ThingType::PatternX] + m_xPattern) + * m_type->dimensions[ThingType::Layers] + 0) + * m_type->dimensions[ThingType::Height] + yi) + * m_type->dimensions[ThingType::Width] + xi; + if(m_type->dimensions[ThingType::Layers] > 1) { + int maskIndex = ((((((m_animation % m_type->dimensions[ThingType::AnimationPhases]) + * m_type->dimensions[ThingType::PatternZ] + m_zPattern) + * m_type->dimensions[ThingType::PatternY] + m_yPattern) + * m_type->dimensions[ThingType::PatternX] + m_xPattern) + * m_type->dimensions[ThingType::Layers] + 1) + * m_type->dimensions[ThingType::Height] + yi) + * m_type->dimensions[ThingType::Width] + xi; + int spriteId = m_type->sprites[maskIndex]; + if(!spriteId) + continue; + TexturePtr maskTex = g_sprites.getSpriteTexture(spriteId); + outfitProgram->setUniformTexture(MASK_TEXTURE_UNIFORM, maskTex, 1); + } - // body - g_graphics.bindColor(m_outfit.getBodyColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask); + int spriteId = m_type->sprites[sprIndex]; + if(!spriteId) + continue; - // legs - g_graphics.bindColor(m_outfit.getLegsColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask); + TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); - // feet - g_graphics.bindColor(m_outfit.getFeetColor()); - internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask); - - // restore default blend func - g_graphics.bindBlendFunc(Fw::BlendDefault); - g_graphics.bindColor(Fw::white); + Rect drawRect(((p + m_walkOffset).x - xi*32) - m_type->parameters[ThingType::DisplacementX], + ((p + m_walkOffset).y - yi*32) - m_type->parameters[ThingType::DisplacementY], + 32, 32); + g_painter.drawTexturedRect(drawRect, spriteTex); + } } + + g_painter.releaseCustomProgram(); } } @@ -115,11 +155,11 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& rect) healthRect.setWidth((m_healthPercent / 100.0) * 25); // draw - g_graphics.bindColor(Fw::black); - g_graphics.drawFilledRect(backgroundRect); + g_painter.setColor(Fw::black); + g_painter.drawFilledRect(backgroundRect); - g_graphics.bindColor(fillColor); - g_graphics.drawFilledRect(healthRect); + g_painter.setColor(fillColor); + g_painter.drawFilledRect(healthRect); m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor); } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 54a7e8e1..ea63e35e 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -28,7 +28,9 @@ #include "missile.h" #include #include - +#include +#include +#include Map g_map; Map::Map() @@ -36,12 +38,20 @@ Map::Map() setVisibleSize(Size(MAP_VISIBLE_WIDTH, MAP_VISIBLE_HEIGHT)); } +PainterShaderProgramPtr program; void Map::draw(const Rect& rect) { - if(!m_framebuffer) + if(!m_framebuffer) { m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS)); - g_graphics.bindColor(Fw::white); + + program = PainterShaderProgramPtr(new PainterShaderProgram); + program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + program->addShaderFromSourceFile(Shader::Fragment, "/shadertest.frag"); + assert(program->link()); + } + + g_painter.setColor(Fw::white); m_framebuffer->bind(); // draw offsets @@ -80,10 +90,13 @@ void Map::draw(const Rect& rect) } } - m_framebuffer->unbind(); + m_framebuffer->release(); - g_graphics.bindColor(Fw::white); + + g_painter.setCustomProgram(program); + g_painter.setColor(Fw::white); m_framebuffer->draw(rect); + g_painter.releaseCustomProgram(); // calculate stretch factor float horizontalStretchFactor = rect.width() / (float)(m_visibleSize.width() * NUM_TILE_PIXELS); diff --git a/src/otclient/core/spritemanager.cpp b/src/otclient/core/spritemanager.cpp index f1d5d0c5..731e66c1 100644 --- a/src/otclient/core/spritemanager.cpp +++ b/src/otclient/core/spritemanager.cpp @@ -118,30 +118,7 @@ TexturePtr SpriteManager::loadSpriteTexture(int id) return TexturePtr(new Texture(32, 32, 4, pixels)); } -TexturePtr SpriteManager::loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask) -{ - auto pixels = spriteTex->getPixels(); - - static uint32 maskColors[4] = { Fw::red, Fw::green, Fw::blue, Fw::yellow }; - uint32 maskColor = maskColors[mask]; - uint32 whiteColor = Fw::white; - uint32 alphaColor = Fw::alpha; - - // convert pixels - // masked color -> white color - // any other color -> alpha color - for(int i=0;i<4096;i+=4) { - uint32& currentColor = *(uint32*)&pixels[i]; - if(currentColor == maskColor) - currentColor = whiteColor; - else - currentColor = alphaColor; - } - - return TexturePtr(new Texture(32, 32, 4, &pixels[0])); -} - -TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask) +TexturePtr SpriteManager::getSpriteTexture(int id) { if(id == 0) return g_graphics.getEmptyTexture(); @@ -149,17 +126,11 @@ TexturePtr SpriteManager::getSpriteTexture(int id, Otc::SpriteMask mask) assert(id > 0 && id <= m_spritesCount); // load sprites on demand - Sprite& sprite = m_sprites[id-1]; - if(!sprite.texture) - sprite.texture = loadSpriteTexture(id); + TexturePtr& sprite = m_sprites[id-1]; + if(!sprite) + sprite = loadSpriteTexture(id); //TODO: release unused sprites textures after X seconds // to avoid massive texture allocations - - if(mask != Otc::SpriteNoMask) { - if(!sprite.masks[mask]) - sprite.masks[mask] = loadSpriteMask(sprite.texture, mask); - return sprite.masks[mask]; - } else - return sprite.texture; + return sprite; } diff --git a/src/otclient/core/spritemanager.h b/src/otclient/core/spritemanager.h index 0c97f8a2..7b1dfb2c 100644 --- a/src/otclient/core/spritemanager.h +++ b/src/otclient/core/spritemanager.h @@ -26,11 +26,6 @@ #include "declarations.h" #include -struct Sprite { - TexturePtr texture; - TexturePtr masks[4]; -}; - class SpriteManager { public: @@ -42,16 +37,15 @@ public: uint32 getSignature() { return m_signature; } int getSpritesCount() { return m_spritesCount; } - TexturePtr getSpriteTexture(int id, Otc::SpriteMask mask = Otc::SpriteNoMask); + TexturePtr getSpriteTexture(int id); private: TexturePtr loadSpriteTexture(int id); - TexturePtr loadSpriteMask(TexturePtr spriteTex, Otc::SpriteMask mask); uint32 m_signature; uint16 m_spritesCount; std::stringstream m_fin; - std::vector m_sprites; + std::vector m_sprites; TexturePtr m_transparentSprite; }; diff --git a/src/otclient/core/thing.cpp b/src/otclient/core/thing.cpp index 6066047a..109a0d0a 100644 --- a/src/otclient/core/thing.cpp +++ b/src/otclient/core/thing.cpp @@ -34,7 +34,7 @@ Thing::Thing() : m_id(0) m_type = g_thingsType.getEmptyThingType(); } -void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) +void Thing::internalDraw(const Point& p, int layers) { for(int yi = 0; yi < m_type->dimensions[ThingType::Height]; yi++) { for(int xi = 0; xi < m_type->dimensions[ThingType::Width]; xi++) { @@ -50,12 +50,12 @@ void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask) if(!spriteId) continue; - TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId, mask); + TexturePtr spriteTex = g_sprites.getSpriteTexture(spriteId); Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX], (p.y - yi*32) - m_type->parameters[ThingType::DisplacementY], 32, 32); - g_graphics.drawTexturedRect(drawRect, spriteTex); + g_painter.drawTexturedRect(drawRect, spriteTex); } } } diff --git a/src/otclient/core/thing.h b/src/otclient/core/thing.h index 3614d512..29328d47 100644 --- a/src/otclient/core/thing.h +++ b/src/otclient/core/thing.h @@ -63,7 +63,7 @@ public: virtual LocalPlayerPtr asLocalPlayer() { return nullptr; } protected: - void internalDraw(const Point& p, int layers, Otc::SpriteMask mask = Otc::SpriteNoMask); + void internalDraw(const Point& p, int layers); uint32 m_id; Position m_position; diff --git a/src/otclient/otclient.cpp b/src/otclient/otclient.cpp index ef2c282a..6d5e4f47 100644 --- a/src/otclient/otclient.cpp +++ b/src/otclient/otclient.cpp @@ -36,6 +36,5 @@ void OTClient::init(const std::vector& args) g_modules.discoverModules(); g_modules.autoLoadModules(100); g_modules.ensureModuleLoaded("client"); - g_modules.ensureModuleLoaded("game"); g_modules.autoLoadModules(1000); } diff --git a/src/otclient/ui/uicreature.cpp b/src/otclient/ui/uicreature.cpp index f78751e2..76973b84 100644 --- a/src/otclient/ui/uicreature.cpp +++ b/src/otclient/ui/uicreature.cpp @@ -34,7 +34,7 @@ void UICreature::render() renderSelf(); if(m_creature) { - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_creature->draw(m_rect.bottomRight() - Point(32, 32) + m_creatureMargin); } diff --git a/src/otclient/ui/uiitem.cpp b/src/otclient/ui/uiitem.cpp index da19fb0c..7a98c979 100644 --- a/src/otclient/ui/uiitem.cpp +++ b/src/otclient/ui/uiitem.cpp @@ -34,7 +34,7 @@ void UIItem::render() renderSelf(); if(m_item) { - g_graphics.bindColor(Fw::white); + g_painter.setColor(Fw::white); m_item->draw(m_rect.bottomRight() - Point(32, 32) + m_itemMargin); } diff --git a/src/otclient/ui/uimap.cpp b/src/otclient/ui/uimap.cpp index 3523562a..2359b539 100644 --- a/src/otclient/ui/uimap.cpp +++ b/src/otclient/ui/uimap.cpp @@ -35,8 +35,8 @@ void UIMap::render() { renderSelf(); - g_graphics.bindColor(Fw::black); - g_graphics.drawBoundingRect(m_mapRect.expanded(1)); + g_painter.setColor(Fw::black); + g_painter.drawBoundingRect(m_mapRect.expanded(1)); g_map.draw(m_mapRect); renderChildren(); @@ -78,6 +78,6 @@ void UIMap::onGeometryUpdate(const Rect& oldRect, const Rect& newRect) Size mapSize(g_map.getVibibleSize().width() * Map::NUM_TILE_PIXELS, g_map.getVibibleSize().height() * Map::NUM_TILE_PIXELS); mapSize.scale(mapRect.size(), Fw::KeepAspectRatio); - m_mapRect.setSize(mapSize); + m_mapRect.resize(mapSize); m_mapRect.moveCenter(newRect.center()); } diff --git a/tools/lua-binding-generator/generate_lua_bindings.lua b/tools/lua-binding-generator/generate_lua_bindings.lua index b77022d2..a887bd2f 100755 --- a/tools/lua-binding-generator/generate_lua_bindings.lua +++ b/tools/lua-binding-generator/generate_lua_bindings.lua @@ -15,16 +15,16 @@ if not io.open(cppclassheader, 'r') then return false end -function string.matchcount(str, pattern) +function string:matchcount(pattern) local count = 0 - for w in str:gmatch(pattern) do count = count + 1 end + for w in self:gmatch(pattern) do count = count + 1 end return count end -function string.splitlines(str) +function string:splitlines() local t = {} local function helper(line) table.insert(t, line) return "" end - helper((str:gsub("(.-)\r?\n", helper))) + helper((self:gsub("(.-)\r?\n", helper))) return t end @@ -34,7 +34,7 @@ for line in io.lines(cppclassheader) do foundclassname = line:match('^class ([%w_]+)') if foundclassname then if not cppclassname then - guessedclassname = cppclassheader:match('([%w_]+).h'):lower() + guessedclassname = cppclassheader:match('([%w_]+)\.h$'):lower() if foundclassname:lower() == guessedclassname then cppclassname = foundclassname end @@ -69,8 +69,9 @@ for line in io.lines(cppclassheader) do elseif line:match('private:') or line:match('protected:') then publicmethods = false elseif publicmethods then - for funcname,args in line:gmatch(' *[%w :_]* ([%w_]+)%(([^%(]*%)) *[;{].*$') do - if funcname ~= cppclassname then + funcname, args = line:match('^ *[%w <>&\*:_]* ([%w_]+)%(([^%)]*%))[%w ]*[;{].*$') + if funcname then + if funcname ~= cppclassname and funcname ~= 'create' then numargs = args:matchcount('[^,)]+[,)]') if cppclassinstance then