use GLSL shaders

This commit is contained in:
Eduardo Bart 2011-12-06 22:31:55 -02:00
parent cf0aab6d4d
commit 7eead50806
64 changed files with 1219 additions and 630 deletions

8
TODO
View File

@ -14,11 +14,10 @@ fix moving windows and tooltips conflicts
todo display otclient icon in window bar todo display otclient icon in window bar
remake otui styles states system remake otui styles states system
padding padding
break UILabel lines
rename Game to g_game, etc rename Game to g_game, etc
implement Console key binding implement Console key binding
fatal error if sprite load fails
impl vertical sync, clipboard impl vertical sync, clipboard
crash handler crash handler
modify COnnection::poll() modify COnnection::poll()
@ -29,4 +28,7 @@ bind every global lua function in a static class
use metatable for Point,Rect,Color,Size lua classes use metatable for Point,Rect,Color,Size lua classes
lua binder generator lua binder generator
restore win32 platform restore win32 platform
set special types for g_configs like lists/point/size 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

View File

@ -0,0 +1,5 @@
function dumpWidgets()
for i=1,UI.root:getChildCount() do
print(UI.root:getChildByIndex(i):getId())
end
end

View File

@ -34,7 +34,7 @@ local function completeCommand()
local cursorPos = commandLineEdit:getCursorPos() local cursorPos = commandLineEdit:getCursorPos()
if cursorPos == 0 then return end if cursorPos == 0 then return end
local commandBegin = string.sub(commandLineEdit:getText(), 1, cursorPos) local commandBegin = commandLineEdit:getText():sub(1, cursorPos)
local possibleCommands = {} local possibleCommands = {}
-- create a list containing all globals -- create a list containing all globals
@ -43,7 +43,7 @@ local function completeCommand()
-- match commands -- match commands
for k,v in pairs(allVars) do 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) table.insert(possibleCommands, k)
end end
end end
@ -63,9 +63,9 @@ local function completeCommand()
if #possibleCommands[1] < cursorPos then if #possibleCommands[1] < cursorPos then
break break
end end
expandedComplete = commandBegin .. string.sub(possibleCommands[1], cursorPos, cursorPos) expandedComplete = commandBegin .. possibleCommands[1]:sub(cursorPos, cursorPos)
for i,v in ipairs(possibleCommands) do for i,v in ipairs(possibleCommands) do
if string.sub(v, 1, #expandedComplete) ~= expandedComplete then if v:sub(1, #expandedComplete) ~= expandedComplete then
done = true done = true
end end
end end

View File

@ -8,11 +8,9 @@ Module
autoLoad: true autoLoad: true
autoLoadPriority: 20 autoLoadPriority: 20
dependencies:
- core
onLoad: | onLoad: |
require 'console' require 'console'
require 'commands'
Console.init() Console.init()
return true return true

View File

@ -3,7 +3,7 @@ Client = { }
-- TODO: load and save configurations -- TODO: load and save configurations
function Client.init() function Client.init()
g_window.move({ x=220, y=220 }) 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.setTitle('OTClient')
g_window.setIcon('clienticon.png') g_window.setIcon('clienticon.png')
return true return true

View File

@ -23,8 +23,8 @@ local function onError(protocol, error)
end end
local function onMotd(protocol, motd) local function onMotd(protocol, motd)
motdNumber = tonumber(string.sub(motd, 0, string.find(motd, "\n"))) motdNumber = tonumber(motd:sub(0, motd:find("\n")))
motdMessage = string.sub(motd, string.find(motd, "\n") + 1, string.len(motd)) motdMessage = motd:sub(motd:find("\n") + 1, #motd)
TopMenu.getButton('motdButton'):show() TopMenu.getButton('motdButton'):show()
end end

View File

@ -7,7 +7,7 @@ local vsyncEnabled = false
function getConfig(name, default) function getConfig(name, default)
if g_configs.exists(name) then 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 if val == 'true' or val == 'false' then
return toboolean(val) return toboolean(val)
else else

View File

@ -1,4 +1,3 @@
-- AnchorEdge
AnchorNone = 0 AnchorNone = 0
AnchorTop = 1 AnchorTop = 1
AnchorBottom = 2 AnchorBottom = 2
@ -15,9 +14,6 @@ LogFatal = 4
ActiveFocusReason = 2 ActiveFocusReason = 2
EmptyFunction = function() end
-- KeyCodes
KeyUnknown = 0 KeyUnknown = 0
KeyEscape = 1 KeyEscape = 1
KeyTab = 2 KeyTab = 2
@ -57,7 +53,7 @@ KeyLeftParen = 40 -- (
KeyRightParen = 41 -- ) KeyRightParen = 41 -- )
KeyAsterisk = 42 -- * KeyAsterisk = 42 -- *
KeyPlus = 43 -- + KeyPlus = 43 -- +
KeyComma = 44 -- KeyComma = 44 -- ,
KeyMinus = 45 -- - KeyMinus = 45 -- -
KeyPeriod = 46 -- . KeyPeriod = 46 -- .
KeySlash = 47 -- / KeySlash = 47 -- /

View File

@ -7,10 +7,14 @@ Module
onLoad: | onLoad: |
require 'ext/table' require 'ext/table'
require 'ext/string' require 'ext/string'
require 'constants' require 'util/point'
require 'util/size'
require 'util/color'
require 'util/rect'
require 'const'
require 'util' require 'util'
require 'dispatcher' require 'dispatcher'
require 'widget' require 'widget'
require 'ui' require 'ui'
require 'gfx' require 'effects'
return true return true

View File

@ -1,43 +1,33 @@
local eventId = 0 local eventId = 0
local eventsTable = { } local eventList = {}
local orig = { scheduleEvent = scheduleEvent,
addEvent = addEvent }
-- fix original scheduleEvent
function scheduleEvent(func, delay) function scheduleEvent(func, delay)
eventId = eventId + 1 eventId = eventId + 1
local id = eventId local id = eventId
local function proxyFunc() local function proxyFunc()
if eventsTable[id] then if eventList[id] then
func() if eventList[id].active then
eventsTable[id] = nil func()
end
eventList[id] = nil
end end
end end
eventsTable[id] = proxyFunc eventList[id] = { func = proxyFunc, active = true }
orig.scheduleEvent(proxyFunc, delay) if delay and delay > 0 then
g_dispatcher.scheduleEvent(proxyFunc, delay)
else
g_dispatcher.addEvent(proxyFunc, false)
end
return id return id
end end
-- FIXME: the event function can be collected function addEvent(func)
-- and the dispatcher would call an invalid function, generating an warning return scheduleEvent(func, 0)
end
function removeEvent(id) function removeEvent(id)
if id and eventsTable[id] then if id and eventList[id] then
eventsTable[id] = nil eventList[id].active = false
return true return true
end end
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

View File

@ -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 elapsed then elapsed = 0 end
if not time then time = 250 end if not time then time = 250 end
widget:setOpacity(math.min((255*elapsed)/time, 255)) widget:setOpacity(math.min((255*elapsed)/time, 255))
@ -11,7 +11,7 @@ function GFX.fadeIn(widget, time, elapsed)
end end
end end
function GFX.fadeOut(widget, time, elapsed) function Effects.fadeOut(widget, time, elapsed)
if not elapsed then elapsed = 0 end if not elapsed then elapsed = 0 end
if not time then time = 250 end if not time then time = 250 end
widget:setOpacity((255*(time - elapsed))/time) widget:setOpacity((255*(time - elapsed))/time)

View File

@ -13,12 +13,12 @@ function string:starts(start)
return self:sub(1, #start) == start return self:sub(1, #start) == start
end end
function string.trim(str) function string:trim()
return str:match'^%s*(.*%S)' or '' return self:match('^%s*(.*%S)') or ''
end end
function toboolean(str) function toboolean(str)
str = string.trim(str) str = str:trim()
if str == '1' or str == 'true' then if str == '1' or str == 'true' then
return true return true
end end

View File

@ -1,7 +1,7 @@
function table.dump(t, depth) function table.dump(t, depth)
if not depth then depth = 0 end if not depth then depth = 0 end
for k,v in pairs(t) do for k,v in pairs(t) do
str = string.rep(' ', depth * 2) .. k .. ': ' str = (' '):rep(depth * 2) .. k .. ': '
if type(v) ~= "table" then if type(v) ~= "table" then
print(str .. tostring(v)) print(str .. tostring(v))
else else

View File

@ -6,10 +6,8 @@ function print(...)
Logger.log(LogInfo, msg) Logger.log(LogInfo, msg)
end end
function createEnvironment() function fatal(msg)
local env = { } Logger.log(LogFatal, msg)
setmetatable(env, { __index = _G} )
return env
end end
function connect(object, signalsAndSlots, pushFront) function connect(object, signalsAndSlots, pushFront)
@ -28,10 +26,10 @@ function connect(object, signalsAndSlots, pushFront)
end end
end end
function dumpWidgets() function createEnvironment()
for i=1,UI.root:getChildCount() do local env = { }
print(UI.root:getChildByIndex(i):getId()) setmetatable(env, { __index = _G} )
end return env
end end
function getCallingScriptSourcePath(depth) function getCallingScriptSourcePath(depth)

View File

@ -16,4 +16,4 @@ function UIWidget:setMargin(...)
self:setMarginBottom(params[3]) self:setMarginBottom(params[3])
self:setMarginLeft(params[4]) self:setMarginLeft(params[4])
end end
end end

View File

@ -28,7 +28,7 @@ function MessageBox.create(title, text, flags)
if flags == MessageBoxOk then if flags == MessageBoxOk then
buttonRight:setText("Ok") buttonRight:setText("Ok")
box.onOk = EmptyFunction box.onOk = function() end
buttonRight.onClick = function() buttonRight.onClick = function()
box.onOk() box.onOk()
box:destroy() box:destroy()
@ -37,7 +37,7 @@ function MessageBox.create(title, text, flags)
window.onEscape = buttonRight.onClick window.onEscape = buttonRight.onClick
elseif flags == MessageBoxCancel then elseif flags == MessageBoxCancel then
buttonRight:setText("Cancel") buttonRight:setText("Cancel")
box.onCancel = EmptyFunction box.onCancel = function() end
buttonRight.onClick = function() buttonRight.onClick = function()
box.onCancel() box.onCancel()
box:destroy() box:destroy()

View File

@ -28,7 +28,7 @@ function ToolTip.display(text)
local size = label:getSize() local size = label:getSize()
size.width = size.width + 4 size.width = size.width + 4
size.height = size.height + 4 size.height = size.height + 4
currentToolTip:setSize(size) currentToolTip:resize(size)
moveToolTip(currentToolTip) moveToolTip(currentToolTip)
end end
end end

View File

@ -135,6 +135,7 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/font.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/font.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/painter.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/texture.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/animatedtexture.cpp
@ -142,6 +143,9 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/texturemanager.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/borderimage.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/borderimage.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp ${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/shader.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/shaderprogram.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/paintershaderprogram.cpp
# framework otml # framework otml
${CMAKE_CURRENT_LIST_DIR}/otml/otmldocument.cpp ${CMAKE_CURRENT_LIST_DIR}/otml/otmldocument.cpp

View File

@ -31,7 +31,9 @@
#include <framework/ui/uimanager.h> #include <framework/ui/uimanager.h>
#include <framework/ui/uiwidget.h> #include <framework/ui/uiwidget.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/graphics/painter.h>
#include <framework/luascript/luainterface.h> #include <framework/luascript/luainterface.h>
#include <../../oglrenderer/graphics/painter.h>
Application *g_app = nullptr; Application *g_app = nullptr;
@ -134,7 +136,6 @@ void Application::terminate()
// terminate graphics // terminate graphics
if(m_appFlags & Fw::AppEnableGraphics) { if(m_appFlags & Fw::AppEnableGraphics) {
g_ui.terminate(); g_ui.terminate();
g_graphics.terminate();
g_window.terminate(); g_window.terminate();
} }
@ -217,8 +218,8 @@ void Application::render()
void Application::resize(const Size& size) void Application::resize(const Size& size)
{ {
g_graphics.resize(size);
g_ui.resize(size); g_ui.resize(size);
g_graphics.resize(size);
} }
void Application::inputEvent(const InputEvent& event) void Application::inputEvent(const InputEvent& event)

View File

@ -79,15 +79,13 @@ bool Module::load()
} }
} }
if(m_loadCallback) { if(m_loadCallback && !m_loadCallback()) {
m_loaded = m_loadCallback(); logError("Unable to load module '", m_name, "' because its onLoad event returned false");
if(!m_loaded) { return false;
logError("Unable to load module '", m_name, "' because its onLoad event returned false");
return false;
}
} }
logInfo("Loaded module '", m_name, "'"); logInfo("Loaded module '", m_name, "'");
m_loaded = true;
return true; return true;
} }

View File

@ -29,7 +29,7 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra
Texture(), Texture(),
m_numFrames(numFrames) m_numFrames(numFrames)
{ {
m_size.setSize(width, height); m_size.resize(width, height);
m_framesTextureId.resize(numFrames); m_framesTextureId.resize(numFrames);
m_framesDelay.resize(numFrames); m_framesDelay.resize(numFrames);

View File

@ -137,68 +137,63 @@ void BorderImage::draw(const Rect& screenCoords)
Rect rectCoords; Rect rectCoords;
Size centerSize = screenCoords.size() - m_bordersSize; Size centerSize = screenCoords.size() - m_bordersSize;
g_graphics.bindTexture(m_texture);
g_graphics.startDrawing();
// first the center // first the center
if(centerSize.area() > 0) { if(centerSize.area() > 0) {
rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(), rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width(),
screenCoords.top() + m_topBorderTexCoords.height(), screenCoords.top() + m_topBorderTexCoords.height(),
centerSize); centerSize);
g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords); g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_centerTexCoords);
} }
// top left corner // top left corner
rectCoords = Rect(screenCoords.topLeft(), rectCoords = Rect(screenCoords.topLeft(),
m_topLeftCornerTexCoords.size()); m_topLeftCornerTexCoords.size());
g_graphics.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords); g_painter.drawTexturedRect(rectCoords, m_texture, m_topLeftCornerTexCoords);
// top // top
rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(), rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width(),
screenCoords.topLeft().y, screenCoords.topLeft().y,
centerSize.width(), centerSize.width(),
m_topBorderTexCoords.height()); m_topBorderTexCoords.height());
g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords); g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_topBorderTexCoords);
// top right corner // top right corner
rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(), rectCoords = Rect(screenCoords.left() + m_topLeftCornerTexCoords.width() + centerSize.width(),
screenCoords.top(), screenCoords.top(),
m_topRightCornerTexCoords.size()); m_topRightCornerTexCoords.size());
g_graphics.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords); g_painter.drawTexturedRect(rectCoords, m_texture, m_topRightCornerTexCoords);
// left // left
rectCoords = Rect(screenCoords.left(), rectCoords = Rect(screenCoords.left(),
screenCoords.top() + m_topLeftCornerTexCoords.height(), screenCoords.top() + m_topLeftCornerTexCoords.height(),
m_leftBorderTexCoords.width(), m_leftBorderTexCoords.width(),
centerSize.height()); centerSize.height());
g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords); g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_leftBorderTexCoords);
// right // right
rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(), rectCoords = Rect(screenCoords.left() + m_leftBorderTexCoords.width() + centerSize.width(),
screenCoords.top() + m_topRightCornerTexCoords.height(), screenCoords.top() + m_topRightCornerTexCoords.height(),
m_rightBorderTexCoords.width(), m_rightBorderTexCoords.width(),
centerSize.height()); centerSize.height());
g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords); g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_rightBorderTexCoords);
// bottom left corner // bottom left corner
rectCoords = Rect(screenCoords.left(), rectCoords = Rect(screenCoords.left(),
screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(), screenCoords.top() + m_topLeftCornerTexCoords.height() + centerSize.height(),
m_bottomLeftCornerTexCoords.size()); m_bottomLeftCornerTexCoords.size());
g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords); g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomLeftCornerTexCoords);
// bottom // bottom
rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(), rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width(),
screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(), screenCoords.top() + m_topBorderTexCoords.height() + centerSize.height(),
centerSize.width(), centerSize.width(),
m_bottomBorderTexCoords.height()); m_bottomBorderTexCoords.height());
g_graphics.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords); g_painter.drawRepeatedTexturedRect(rectCoords, m_texture, m_bottomBorderTexCoords);
// bottom right corner // bottom right corner
rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(), rectCoords = Rect(screenCoords.left() + m_bottomLeftCornerTexCoords.width() + centerSize.width(),
screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(), screenCoords.top() + m_topRightCornerTexCoords.height() + centerSize.height(),
m_bottomRightCornerTexCoords.size()); m_bottomRightCornerTexCoords.size());
g_graphics.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords); g_painter.drawTexturedRect(rectCoords, m_texture, m_bottomRightCornerTexCoords);
g_graphics.stopDrawing();
} }

View File

@ -32,6 +32,9 @@ class Font;
class Image; class Image;
class BorderImage; class BorderImage;
class FrameBuffer; class FrameBuffer;
class Shader;
class ShaderProgram;
class PainterShaderProgram;
typedef std::weak_ptr<Texture> TextureWeakPtr; typedef std::weak_ptr<Texture> TextureWeakPtr;
@ -41,5 +44,9 @@ typedef std::shared_ptr<Font> FontPtr;
typedef std::shared_ptr<Image> ImagePtr; typedef std::shared_ptr<Image> ImagePtr;
typedef std::shared_ptr<BorderImage> BorderImagePtr; typedef std::shared_ptr<BorderImage> BorderImagePtr;
typedef std::shared_ptr<FrameBuffer> FrameBufferPtr; typedef std::shared_ptr<FrameBuffer> FrameBufferPtr;
typedef std::shared_ptr<Shader> ShaderPtr;
typedef std::shared_ptr<ShaderProgram> ShaderProgramPtr;
typedef std::shared_ptr<PainterShaderProgram> PainterShaderProgramPtr;
typedef std::vector<ShaderPtr> ShaderList;
#endif #endif

View File

@ -64,7 +64,7 @@ void Font::renderText(const std::string& text,
const Point& startPos, const Point& startPos,
const Color& color) const Color& color)
{ {
Size boxSize = g_graphics.getScreenSize() - startPos.toSize(); Size boxSize = g_graphics.getViewportSize() - startPos.toSize();
Rect screenCoords(startPos, boxSize); Rect screenCoords(startPos, boxSize);
renderText(text, screenCoords, Fw::AlignTopLeft, color); renderText(text, screenCoords, Fw::AlignTopLeft, color);
} }
@ -85,9 +85,7 @@ void Font::renderText(const std::string& text,
Size textBoxSize; Size textBoxSize;
const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize); const std::vector<Point>& glyphsPositions = calculateGlyphsPositions(text, align, &textBoxSize);
g_graphics.bindColor(color); g_painter.setColor(color);
g_graphics.bindTexture(m_texture);
g_graphics.startDrawing();
for(int i = 0; i < textLenght; ++i) { for(int i = 0; i < textLenght; ++i) {
int glyph = (uchar)text[i]; int glyph = (uchar)text[i];
@ -149,10 +147,8 @@ void Font::renderText(const std::string& text,
} }
// render glyph // render glyph
g_graphics.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords); g_painter.drawTexturedRect(glyphScreenCoords, m_texture, glyphTextureCoords);
} }
g_graphics.stopDrawing();
} }
const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text, const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text,
@ -172,7 +168,7 @@ const std::vector<Point>& Font::calculateGlyphsPositions(const std::string& text
// return if there is no text // return if there is no text
if(textLength == 0) { if(textLength == 0) {
if(textBoxSize) if(textBoxSize)
textBoxSize->setSize(0,m_glyphHeight); textBoxSize->resize(0,m_glyphHeight);
return glyphsPositions; return glyphsPositions;
} }
@ -280,6 +276,6 @@ void Font::calculateGlyphsWidthsAutomatically(const Size& glyphSize)
lastColumnFilledPixels = columnFilledPixels; lastColumnFilledPixels = columnFilledPixels;
} }
// store glyph size // store glyph size
m_glyphsSize[glyph].setSize(width, m_glyphHeight); m_glyphsSize[glyph].resize(width, m_glyphHeight);
} }
} }

View File

@ -26,110 +26,52 @@
FrameBuffer::FrameBuffer(int width, int height) FrameBuffer::FrameBuffer(int width, int height)
{ {
m_fbo = 0;
// create FBO texture // create FBO texture
m_texture = TexturePtr(new Texture(width, height, 4)); m_texture = TexturePtr(new Texture(width, height, 4));
m_texture->enableBilinearFilter(); m_texture->enableBilinearFilter();
// use FBO ext only if supported // generate FBO
if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) { glGenFramebuffers(1, &m_fbo);
m_fallbackOldImp = false; if(!m_fbo)
logFatal("Unable to create framebuffer object");
// generate FBO glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
// attach 2D texture to this FBO // attach 2D texture to this FBO
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch(status) { if(status != GL_FRAMEBUFFER_COMPLETE)
case GL_FRAMEBUFFER_COMPLETE_EXT: logFatal("Unable to create framebuffer object");
//ok
break;
default: // fallback to old implementation
m_fallbackOldImp = true;
break;
}
// restore back buffer // restore back buffer
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glBindFramebuffer(GL_FRAMEBUFFER, 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.");
} }
FrameBuffer::~FrameBuffer() FrameBuffer::~FrameBuffer()
{ {
if(m_fbo) glDeleteFramebuffers(1, &m_fbo);
glDeleteFramebuffers(1, &m_fbo);
} }
void FrameBuffer::bind() void FrameBuffer::bind()
{ {
if(!m_fallbackOldImp) { glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// 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);
glClear(GL_COLOR_BUFFER_BIT); 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
// bind back buffer again glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
// restore graphics viewport // restore graphics viewport
g_graphics.restoreViewport(); glViewport(0, 0, g_graphics.getViewportSize().width(), g_graphics.getViewportSize().height());
} else { g_painter.updateProjectionMatrix(g_graphics.getViewportSize());
// 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);
}
} }
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);
} }

View File

@ -32,8 +32,8 @@ public:
virtual ~FrameBuffer(); virtual ~FrameBuffer();
void bind(); void bind();
void unbind(); void release();
void draw(const Rect& screenCoords, const Rect& framebufferCoords = Rect()); void draw(const Rect& dest);
TexturePtr getTexture() { return m_texture; } TexturePtr getTexture() { return m_texture; }

View File

@ -30,307 +30,48 @@ Graphics g_graphics;
void Graphics::init() void Graphics::init()
{ {
// setup opengl // 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); 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("GPU ", glGetString(GL_RENDERER));
logInfo("OpenGL ", glGetString(GL_VERSION)); logInfo("OpenGL ", glGetString(GL_VERSION));
m_drawing = false; //if(!isExtensionSupported("GL_ARB_framebuffer_object"))
m_opacity = 255; // logFatal("Your graphics card is not supported.");
m_emptyTexture = TexturePtr(new Texture); m_emptyTexture = TexturePtr(new Texture);
bindColor(Fw::white); g_painter.init();
bindBlendFunc(Fw::BlendDefault);
} }
void Graphics::terminate() void Graphics::terminate()
{ {
g_fonts.releaseFonts(); g_fonts.releaseFonts();
g_painter.terminate();
m_emptyTexture.reset(); m_emptyTexture.reset();
} }
bool Graphics::isExtensionSupported(const char *extension) bool Graphics::isExtensionSupported(const char *extension)
{ {
const GLubyte *extensions = NULL; std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS);
const GLubyte *start; auto extensions = Fw::split(extensionsString);
GLubyte *where, *terminator; return std::find(extensions.begin(), extensions.end(), extension) != extensions.end();
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;
} }
void Graphics::resize(const Size& size) void Graphics::resize(const Size& size)
{ {
m_screenSize = size; glViewport(0, 0, size.width(), size.height());
restoreViewport(); g_painter.updateProjectionMatrix(size);
} m_viewportSize = size;
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();
} }
void Graphics::beginRender() void Graphics::beginRender()
{ {
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
} }
void Graphics::endRender() void Graphics::endRender()
{ {
assert(!m_drawing); glFlush();
}
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;
}
}
void Graphics::startDrawing()
{
assert(!m_drawing);
glBegin(GL_QUADS);
m_drawing = true;
}
void Graphics::stopDrawing()
{
assert(m_drawing);
glEnd();
m_drawing = false;
} }

View File

@ -24,64 +24,25 @@
#define GRAPHICS_H #define GRAPHICS_H
#include "declarations.h" #include "declarations.h"
#include "painter.h"
class Graphics class Graphics
{ {
public: public:
/// Initialize default OpenGL states
void init(); void init();
/// Termiante graphics
void terminate(); void terminate();
/// Check if a GL extension is supported
bool isExtensionSupported(const char *extension); bool isExtensionSupported(const char *extension);
/// Resizes OpenGL viewport
void resize(const Size& size); void resize(const Size& size);
/// Restore original viewport
void restoreViewport();
/// Called before every render
void beginRender(); void beginRender();
/// Called after every render
void endRender(); void endRender();
void bindColor(const Color& color); const Size& getViewportSize() const { return m_viewportSize; }
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; }
TexturePtr getEmptyTexture() { return m_emptyTexture; } TexturePtr getEmptyTexture() { return m_emptyTexture; }
private: private:
bool m_drawing; Size m_viewportSize;
int m_opacity;
Size m_screenSize;
TexturePtr m_emptyTexture; TexturePtr m_emptyTexture;
}; };

View File

@ -63,12 +63,12 @@ void Image::draw(const Rect& screenCoords)
else if(texSize.width() > texCoordsSize.width()) else if(texSize.width() > texCoordsSize.width())
texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2; texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2;
g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize)); g_painter.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize));
} else { } else {
if(m_repeated) if(m_repeated)
g_graphics.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords); g_painter.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords);
else else
g_graphics.drawTexturedRect(screenCoords, m_texture, m_textureCoords); g_painter.drawTexturedRect(screenCoords, m_texture, m_textureCoords);
} }
} }
} }

View File

@ -0,0 +1,228 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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"
Painter g_painter;
void Painter::init()
{
setColor(Fw::white);
setOpacity(255);
setCompositionMode(CompositionMode_SourceOver);
PainterShaderProgramPtr program = PainterShaderProgramPtr(new PainterShaderProgram);
program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader);
program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader);
program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader);
program->addShaderFromSourceCode(Shader::Fragment, glslTextureSrcFragmentShader);
program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord");
program->bindAttributeLocation(TEXTURE_COORDS_ATTR, "textureCoord");
assert(program->link());
program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix");
program->bindUniformLocation(PainterShaderProgram::TEXTURE_TRANSFORM_MATRIX_UNIFORM, "textureTransformMatrix");
program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color");
program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity");
program->bindUniformLocation(PainterShaderProgram::TEXTURE_UNIFORM, "texture");
m_drawTexturedProgram = program;
program = PainterShaderProgramPtr(new PainterShaderProgram);
program->addShaderFromSourceCode(Shader::Vertex, glslMainVertexShader);
program->addShaderFromSourceCode(Shader::Vertex, glslPositionOnlyVertexShader);
program->addShaderFromSourceCode(Shader::Fragment, glslMainFragmentShader);
program->addShaderFromSourceCode(Shader::Fragment, glslSolidColorFragmentShader);
program->bindAttributeLocation(VERTEX_COORDS_ATTR, "vertexCoord");
assert(program->link());
program->bindUniformLocation(PainterShaderProgram::PROJECTION_MATRIX_UNIFORM, "projectionMatrix");
program->bindUniformLocation(PainterShaderProgram::COLOR_UNIFORM, "color");
program->bindUniformLocation(PainterShaderProgram::OPACITY_UNIFORM, "opacity");
m_drawSolidColorProgram = program;
}
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::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;
GLfloat vertexCoords[] = { (float)dest.left(), (float)dest.top(),
(float)dest.right()+1, (float)dest.top(),
(float)dest.left(), (float)dest.bottom()+1,
(float)dest.right()+1, (float)dest.bottom()+1 };
GLfloat textureCoords[] = { (float)src.left(), (float)src.top(),
(float)src.right()+1, (float)src.top(),
(float)src.left(), (float)src.bottom()+1,
(float)src.right()+1, (float)src.bottom()+1 };
m_drawTexturedProgram->prepareForDraw();
m_drawTexturedProgram->setProjectionMatrix(m_projectionMatrix);
m_drawTexturedProgram->setOpacity(m_currentOpacity);
m_drawTexturedProgram->setColor(m_currentColor);
m_drawTexturedProgram->setTexture(texture);
m_drawTexturedProgram->setVertexCoords(vertexCoords);
m_drawTexturedProgram->setTextureCoords(textureCoords);
m_drawTexturedProgram->drawTriangleStrip(4);
m_drawTexturedProgram->releaseFromDraw();
}
void Painter::drawRepeatedTexturedRect(const Rect& dest, const TexturePtr& texture, const Rect& src)
{
if(dest.isEmpty() || src.isEmpty() || !texture->getId())
return;
//TODO: use vertex arrays..
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());
drawTexturedRect(partialDest, texture, partialSrc);
}
}
}
void Painter::drawFilledRect(const Rect& dest)
{
if(dest.isEmpty())
return;
GLfloat right = dest.right()+1;
GLfloat bottom = dest.bottom()+1;
GLfloat top = dest.top();
GLfloat left = dest.left();
GLfloat vertexCoords[] = { left, top,
right, top,
left, bottom,
right, bottom };
m_drawSolidColorProgram->prepareForDraw();
m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix);
m_drawSolidColorProgram->setOpacity(m_currentOpacity);
m_drawSolidColorProgram->setColor(m_currentColor);
m_drawSolidColorProgram->setVertexCoords(vertexCoords);
m_drawSolidColorProgram->drawTriangleStrip(4);
m_drawSolidColorProgram->releaseFromDraw();
}
void Painter::drawBoundingRect(const Rect& dest, int innerLineWidth)
{
if(dest.isEmpty() || innerLineWidth == 0)
return;
GLfloat right = dest.right()+1;
GLfloat bottom = dest.bottom()+1;
GLfloat top = dest.top();
GLfloat left = dest.left();
GLfloat w = innerLineWidth;
GLfloat vertexCoords[] = { left, top,
right, top,
left, top+w,
right, top+w,
right-w, top+w,
right, bottom,
right-w, bottom,
right-w, bottom-w,
left, bottom,
left, bottom-w,
left+w, bottom-w,
left, top+w,
left+w, top+w };
m_drawSolidColorProgram->prepareForDraw();
m_drawSolidColorProgram->setProjectionMatrix(m_projectionMatrix);
m_drawSolidColorProgram->setOpacity(m_currentOpacity);
m_drawSolidColorProgram->setColor(m_currentColor);
m_drawSolidColorProgram->setVertexCoords(vertexCoords);
m_drawSolidColorProgram->drawTriangleStrip(13);
m_drawSolidColorProgram->releaseFromDraw();
}
void Painter::setCompositionMode(Painter::CompositionMode compositionMode)
{
switch(compositionMode) {
case CompositionMode_SourceOver:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case CompositionMode_ColorizeDest:
glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
break;
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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"
class Painter
{
public:
enum CompositionMode {
CompositionMode_SourceOver,
CompositionMode_ColorizeDest
};
void init();
void terminate();
void updateProjectionMatrix(const Size& viewportSize, bool inverseYAxis = false);
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 setCompositionMode(CompositionMode compositionMode);
private:
PainterShaderProgramPtr m_drawTexturedProgram;
PainterShaderProgramPtr m_drawSolidColorProgram;
GLfloat m_projectionMatrix[3][3];
Color m_currentColor;
GLfloat m_currentOpacity;
};
extern Painter g_painter;
#endif

View File

@ -0,0 +1,99 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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"
void PainterShaderProgram::setProjectionMatrix(float projectionMatrix[3][3])
{
setUniformValue(PROJECTION_MATRIX_UNIFORM, projectionMatrix, true);
}
void PainterShaderProgram::setColor(const Color& color)
{
setUniformValue(COLOR_UNIFORM,
color.r() / 255.0f,
color.g() / 255.0f,
color.b() / 255.0f,
color.a() / 255.0f);
}
void PainterShaderProgram::setOpacity(GLfloat opacity)
{
setUniformValue(OPACITY_UNIFORM, opacity);
}
void PainterShaderProgram::setTexture(const TexturePtr& texture)
{
float w = texture->getGlSize().width();
float h = texture->getGlSize().height();
GLfloat textureTransformMatrix[2][2] = {
{ 1.0f/w, 0.0f },
{ 0.0f, 1.0f/h }
};
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture->getId());
setUniformValue(TEXTURE_UNIFORM, 0);
setUniformValue(TEXTURE_TRANSFORM_MATRIX_UNIFORM, textureTransformMatrix, true);
}
void PainterShaderProgram::setVertexCoords(const GLfloat *vertices)
{
enableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR);
setAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR, vertices, 2);
}
void PainterShaderProgram::setTextureCoords(const GLfloat *textureCoords)
{
enableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR);
setAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR, textureCoords, 2);
m_mustDisableTexCoordsArray = true;
}
void PainterShaderProgram::prepareForDraw()
{
assert(bind());
}
void PainterShaderProgram::drawTriangleStrip(int numVertices)
{
glDrawArrays(GL_TRIANGLE_STRIP, 0, numVertices);
}
void PainterShaderProgram::releaseFromDraw()
{
if(m_mustDisableTexCoordsArray) {
disableAttributeArray(PainterShaderProgram::TEXTURE_COORDS_ATTR);
m_mustDisableTexCoordsArray = false;
}
if(m_mustDisableVertexArray) {
disableAttributeArray(PainterShaderProgram::VERTEX_COORDS_ATTR);
m_mustDisableVertexArray = false;
}
//release();
}

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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"
class PainterShaderProgram : public ShaderProgram
{
public:
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
};
void setProjectionMatrix(GLfloat projectionMatrix[3][3]);
void setColor(const Color& color);
void setOpacity(GLfloat opacity);
void setTexture(const TexturePtr& texture);
void setVertexCoords(const GLfloat *vertices);
void setTextureCoords(const GLfloat *textureCoords);
void prepareForDraw();
void drawTriangleStrip(int numVertices);
void releaseFromDraw();
private:
Boolean<false> m_mustDisableVertexArray;
Boolean<false> m_mustDisableTexCoordsArray;
};
#endif

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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 char *glslMainVertexShader = "\n\
vec4 calculatePosition();\n\
void main() {\n\
gl_Position = calculatePosition();\n\
}\n";
static const char *glslMainWithTexCoordsVertexShader = "\n\
attribute vec2 textureCoord;\n\
uniform mat2 textureTransformMatrix;\n\
varying vec2 textureCoords;\n\
vec4 calculatePosition();\n\
void main()\n\
{\n\
gl_Position = calculatePosition();\n\
textureCoords = textureTransformMatrix * textureCoord;\n\
}\n";
static const char *glslPositionOnlyVertexShader = "\n\
attribute vec2 vertexCoord;\n\
uniform mat3 projectionMatrix;\n\
vec4 calculatePosition() {\n\
return vec4(projectionMatrix * vec3(vertexCoord.xy, 1), 1);\n\
}\n";
static const char *glslMainFragmentShader = "\n\
uniform float opacity;\n\
vec4 calculatePixel();\n\
void main()\n\
{\n\
gl_FragColor = calculatePixel() * opacity;\n\
}\n";
static const char *glslTextureSrcFragmentShader = "\n\
varying vec2 textureCoords;\n\
uniform vec4 color;\n\
uniform sampler2D texture;\n\
vec4 calculatePixel() {\n\
return texture2D(texture, textureCoords) * color;\n\
}\n";
static const char *glslSolidColorFragmentShader = "\n\
uniform vec4 color;\n\
vec4 calculatePixel() {\n\
return color;\n\
}\n";

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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"
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)
{
const char *c_source = sourceCode.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::ifstream fin(sourceFile);
std::string sourceCode((std::istreambuf_iterator<char>(fin)), std::istreambuf_iterator<char>());
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<char> buf(infoLogLength);
glGetShaderInfoLog(m_shaderId, infoLogLength-1, NULL, &buf[0]);
infoLog = &buf[0];
}
return infoLog;
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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<char> 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 < 10);
m_uniformLocations[location] = glGetUniformLocation(m_programId, name);
}

View File

@ -0,0 +1,93 @@
/*
* Copyright (c) 2010-2011 OTClient <https://github.com/edubart/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 = 10
};
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();
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, 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, 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<GLint, MAX_UNIFORM_LOCATIONS> m_uniformLocations;
};
#endif

View File

@ -36,7 +36,6 @@ Texture::Texture(int width, int height, int channels, uchar *pixels)
Texture::~Texture() Texture::~Texture()
{ {
assert(!g_graphics.isDrawing());
// free texture from gl memory // free texture from gl memory
if(m_textureId > 0) if(m_textureId > 0)
glDeleteTextures(1, &m_textureId); glDeleteTextures(1, &m_textureId);
@ -44,9 +43,7 @@ Texture::~Texture()
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height) uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height)
{ {
assert(!g_graphics.isDrawing()); m_size.resize(width, height);
m_size.setSize(width, height);
// gets max texture size supported by the driver // gets max texture size supported by the driver
static GLint maxTexSize = -1; static GLint maxTexSize = -1;
@ -70,7 +67,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
std::vector<uint8> tmp; std::vector<uint8> tmp;
// old opengl drivers only accept power of two dimensions // 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; int glWidth = 1;
while(glWidth < width) while(glWidth < width)
glWidth = glWidth << 1; glWidth = glWidth << 1;
@ -88,7 +85,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
pixels = &tmp[0]; pixels = &tmp[0];
} }
m_glSize.setSize(glWidth, glHeight); m_glSize.resize(glWidth, glHeight);
//} else //} else
// m_glSize = m_size; // m_glSize = m_size;
@ -110,7 +107,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
} }
// load pixels into gl memory // 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 // disable texture border
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 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) // nearest filtering (non smooth)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return id; return id;
} }

View File

@ -37,22 +37,22 @@ public:
virtual void enableBilinearFilter(); virtual void enableBilinearFilter();
/// Get OpenGL texture id /// Get OpenGL texture id
uint getId() const { return m_textureId; } GLuint getId() { return m_textureId; }
/// Copy pixels from OpenGL texture /// Copy pixels from OpenGL texture
std::vector<uint8> getPixels(); std::vector<uint8> getPixels();
int getWidth() const { return m_size.width(); } int getWidth() { return m_size.width(); }
int getHeight() const { return m_size.height(); } int getHeight() { return m_size.height(); }
const Size& getSize() const { return m_size; } const Size& getSize() { return m_size; }
const Size& getGlSize() const { return m_glSize; } const Size& getGlSize() { return m_glSize; }
bool isEmpty() const { return m_textureId == 0; } bool isEmpty() const { return m_textureId == 0; }
protected: 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_size;
Size m_glSize; Size m_glSize;
}; };

View File

@ -36,73 +36,110 @@ void Application::registerLuaFunctions()
// UIWidget // UIWidget
g_lua.registerClass<UIWidget>(); g_lua.registerClass<UIWidget>();
g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create<UIWidget>); g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create<UIWidget>);
g_lua.bindClassMemberFunction<UIWidget>("getId", &UIWidget::getId); g_lua.bindClassMemberFunction<UIWidget>("destroy", &UIWidget::destroy);
g_lua.bindClassMemberFunction<UIWidget>("setId", &UIWidget::setId);
g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled);
g_lua.bindClassMemberFunction<UIWidget>("setEnabled", &UIWidget::setEnabled);
g_lua.bindClassMemberFunction<UIWidget>("isExplicitlyVisible", &UIWidget::isExplicitlyVisible);
g_lua.bindClassMemberFunction<UIWidget>("setVisible", &UIWidget::setVisible); g_lua.bindClassMemberFunction<UIWidget>("setVisible", &UIWidget::setVisible);
g_lua.bindClassMemberFunction<UIWidget>("getWidth", &UIWidget::getWidth); g_lua.bindClassMemberFunction<UIWidget>("setEnabled", &UIWidget::setEnabled);
g_lua.bindClassMemberFunction<UIWidget>("setWidth", &UIWidget::setWidth); g_lua.bindClassMemberFunction<UIWidget>("setPressed", &UIWidget::setPressed);
g_lua.bindClassMemberFunction<UIWidget>("getHeight", &UIWidget::getHeight); g_lua.bindClassMemberFunction<UIWidget>("setId", &UIWidget::setId);
g_lua.bindClassMemberFunction<UIWidget>("setHeight", &UIWidget::setHeight); g_lua.bindClassMemberFunction<UIWidget>("setFocusable", &UIWidget::setFocusable);
g_lua.bindClassMemberFunction<UIWidget>("getSize", &UIWidget::getSize); g_lua.bindClassMemberFunction<UIWidget>("setPhantom", &UIWidget::setPhantom);
g_lua.bindClassMemberFunction<UIWidget>("setSize", &UIWidget::resize);
g_lua.bindClassMemberFunction<UIWidget>("getPosition", &UIWidget::getPosition);
g_lua.bindClassMemberFunction<UIWidget>("getX", &UIWidget::getX);
g_lua.bindClassMemberFunction<UIWidget>("getY", &UIWidget::getY);
g_lua.bindClassMemberFunction<UIWidget>("moveTo", &UIWidget::moveTo);
g_lua.bindClassMemberFunction<UIWidget>("moveChildToIndex", &UIWidget::moveChildToIndex);
g_lua.bindClassMemberFunction<UIWidget>("getParent", &UIWidget::getParent);
g_lua.bindClassMemberFunction<UIWidget>("setParent", &UIWidget::setParent);
g_lua.bindClassMemberFunction<UIWidget>("getBackgroundColor", &UIWidget::getBackgroundColor);
g_lua.bindClassMemberFunction<UIWidget>("setBackgroundColor", &UIWidget::setBackgroundColor);
g_lua.bindClassMemberFunction<UIWidget>("getForegroundColor", &UIWidget::getForegroundColor);
g_lua.bindClassMemberFunction<UIWidget>("setForegroundColor", &UIWidget::setForegroundColor);
g_lua.bindClassMemberFunction<UIWidget>("getOpacity", &UIWidget::getOpacity);
g_lua.bindClassMemberFunction<UIWidget>("setOpacity", &UIWidget::setOpacity);
g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::setStyle); g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::setStyle);
g_lua.bindClassMemberFunction<UIWidget>("applyStyle", &UIWidget::applyStyle); g_lua.bindClassMemberFunction<UIWidget>("setStyleFromNode", &UIWidget::setStyleFromNode);
g_lua.bindClassMemberFunction<UIWidget>("getStyle", &UIWidget::getStyle); //g_lua.bindClassMemberFunction<UIWidget>("setLayout", &UIWidget::setLayout);
g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop); g_lua.bindClassMemberFunction<UIWidget>("setParent", &UIWidget::setParent);
g_lua.bindClassMemberFunction<UIWidget>("setRect", &UIWidget::setRect);
g_lua.bindClassMemberFunction<UIWidget>("setX", &UIWidget::setX);
g_lua.bindClassMemberFunction<UIWidget>("setY", &UIWidget::setY);
g_lua.bindClassMemberFunction<UIWidget>("setWidth", &UIWidget::setWidth);
g_lua.bindClassMemberFunction<UIWidget>("setHeight", &UIWidget::setHeight);
//g_lua.bindClassMemberFunction<UIWidget>("setImage", &UIWidget::setImage);
//g_lua.bindClassMemberFunction<UIWidget>("setFont", &UIWidget::setFont);
g_lua.bindClassMemberFunction<UIWidget>("setOpacity", &UIWidget::setOpacity);
g_lua.bindClassMemberFunction<UIWidget>("setBackgroundColor", &UIWidget::setBackgroundColor);
g_lua.bindClassMemberFunction<UIWidget>("setForegroundColor", &UIWidget::setForegroundColor);
g_lua.bindClassMemberFunction<UIWidget>("setMarginTop", &UIWidget::setMarginTop); g_lua.bindClassMemberFunction<UIWidget>("setMarginTop", &UIWidget::setMarginTop);
g_lua.bindClassMemberFunction<UIWidget>("getMarginBottom", &UIWidget::getMarginBottom);
g_lua.bindClassMemberFunction<UIWidget>("setMarginBottom", &UIWidget::setMarginBottom);
g_lua.bindClassMemberFunction<UIWidget>("getMarginLeft", &UIWidget::getMarginLeft);
g_lua.bindClassMemberFunction<UIWidget>("setMarginLeft", &UIWidget::setMarginLeft);
g_lua.bindClassMemberFunction<UIWidget>("getMarginRight", &UIWidget::getMarginRight);
g_lua.bindClassMemberFunction<UIWidget>("setMarginRight", &UIWidget::setMarginRight); g_lua.bindClassMemberFunction<UIWidget>("setMarginRight", &UIWidget::setMarginRight);
g_lua.bindClassMemberFunction<UIWidget>("isVisible", &UIWidget::isVisible); g_lua.bindClassMemberFunction<UIWidget>("setMarginBottom", &UIWidget::setMarginBottom);
g_lua.bindClassMemberFunction<UIWidget>("isHidden", &UIWidget::isHidden); g_lua.bindClassMemberFunction<UIWidget>("setMarginLeft", &UIWidget::setMarginLeft);
g_lua.bindClassMemberFunction<UIWidget>("isHovered", &UIWidget::isHovered); g_lua.bindClassMemberFunction<UIWidget>("setSizeFixed", &UIWidget::setSizeFixed);
g_lua.bindClassMemberFunction<UIWidget>("isFocused", &UIWidget::isFocused); g_lua.bindClassMemberFunction<UIWidget>("setLastFocusReason", &UIWidget::setLastFocusReason);
g_lua.bindClassMemberFunction<UIWidget>("isPressed", &UIWidget::isPressed); g_lua.bindClassMemberFunction<UIWidget>("resize", &UIWidget::resize);
g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled); g_lua.bindClassMemberFunction<UIWidget>("moveTo", &UIWidget::moveTo);
g_lua.bindClassMemberFunction<UIWidget>("isDisabled", &UIWidget::isDisabled);
g_lua.bindClassMemberFunction<UIWidget>("isActive", &UIWidget::isActive);
g_lua.bindClassMemberFunction<UIWidget>("hide", &UIWidget::hide); g_lua.bindClassMemberFunction<UIWidget>("hide", &UIWidget::hide);
g_lua.bindClassMemberFunction<UIWidget>("show", &UIWidget::show); g_lua.bindClassMemberFunction<UIWidget>("show", &UIWidget::show);
g_lua.bindClassMemberFunction<UIWidget>("disable", &UIWidget::disable);
g_lua.bindClassMemberFunction<UIWidget>("enable", &UIWidget::enable);
g_lua.bindClassMemberFunction<UIWidget>("lock", &UIWidget::lock); g_lua.bindClassMemberFunction<UIWidget>("lock", &UIWidget::lock);
g_lua.bindClassMemberFunction<UIWidget>("unlock", &UIWidget::unlock); g_lua.bindClassMemberFunction<UIWidget>("unlock", &UIWidget::unlock);
g_lua.bindClassMemberFunction<UIWidget>("focus", &UIWidget::focus); g_lua.bindClassMemberFunction<UIWidget>("focus", &UIWidget::focus);
g_lua.bindClassMemberFunction<UIWidget>("getChildren", &UIWidget::getChildren); g_lua.bindClassMemberFunction<UIWidget>("isActive", &UIWidget::isActive);
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildById", &UIWidget::recursiveGetChildById); g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled);
g_lua.bindClassMemberFunction<UIWidget>("getChildById", &UIWidget::getChildById); g_lua.bindClassMemberFunction<UIWidget>("isDisabled", &UIWidget::isDisabled);
g_lua.bindClassMemberFunction<UIWidget>("getChildByIndex", &UIWidget::getChildByIndex); g_lua.bindClassMemberFunction<UIWidget>("isFocused", &UIWidget::isFocused);
g_lua.bindClassMemberFunction<UIWidget>("isHovered", &UIWidget::isHovered);
g_lua.bindClassMemberFunction<UIWidget>("isPressed", &UIWidget::isPressed);
g_lua.bindClassMemberFunction<UIWidget>("isVisible", &UIWidget::isVisible);
g_lua.bindClassMemberFunction<UIWidget>("isHidden", &UIWidget::isHidden);
g_lua.bindClassMemberFunction<UIWidget>("isExplicitlyEnabled", &UIWidget::isExplicitlyEnabled);
g_lua.bindClassMemberFunction<UIWidget>("isExplicitlyVisible", &UIWidget::isExplicitlyVisible);
g_lua.bindClassMemberFunction<UIWidget>("isFocusable", &UIWidget::isFocusable);
g_lua.bindClassMemberFunction<UIWidget>("isPhantom", &UIWidget::isPhantom);
g_lua.bindClassMemberFunction<UIWidget>("isSizeFixed", &UIWidget::isSizeFixed);
g_lua.bindClassMemberFunction<UIWidget>("hasChildren", &UIWidget::hasChildren);
g_lua.bindClassMemberFunction<UIWidget>("hasChild", &UIWidget::hasChild);
g_lua.bindClassMemberFunction<UIWidget>("getId", &UIWidget::getId);
g_lua.bindClassMemberFunction<UIWidget>("getChildCount", &UIWidget::getChildCount); g_lua.bindClassMemberFunction<UIWidget>("getChildCount", &UIWidget::getChildCount);
//g_lua.bindClassMemberFunction<UIWidget>("getLayout", &UIWidget::getLayout);
g_lua.bindClassMemberFunction<UIWidget>("getParent", &UIWidget::getParent);
g_lua.bindClassMemberFunction<UIWidget>("getRootParent", &UIWidget::getRootParent);
g_lua.bindClassMemberFunction<UIWidget>("getPosition", &UIWidget::getPosition);
g_lua.bindClassMemberFunction<UIWidget>("getSize", &UIWidget::getSize);
g_lua.bindClassMemberFunction<UIWidget>("getRect", &UIWidget::getRect);
g_lua.bindClassMemberFunction<UIWidget>("getX", &UIWidget::getX);
g_lua.bindClassMemberFunction<UIWidget>("getY", &UIWidget::getY);
g_lua.bindClassMemberFunction<UIWidget>("getWidth", &UIWidget::getWidth);
g_lua.bindClassMemberFunction<UIWidget>("getHeight", &UIWidget::getHeight);
//g_lua.bindClassMemberFunction<UIWidget>("getImage", &UIWidget::getImage);
//g_lua.bindClassMemberFunction<UIWidget>("getFont", &UIWidget::getFont);
g_lua.bindClassMemberFunction<UIWidget>("getForegroundColor", &UIWidget::getForegroundColor);
g_lua.bindClassMemberFunction<UIWidget>("getBackgroundColor", &UIWidget::getBackgroundColor);
g_lua.bindClassMemberFunction<UIWidget>("getOpacity", &UIWidget::getOpacity);
g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop);
g_lua.bindClassMemberFunction<UIWidget>("getMarginRight", &UIWidget::getMarginRight);
g_lua.bindClassMemberFunction<UIWidget>("getMarginBottom", &UIWidget::getMarginBottom);
g_lua.bindClassMemberFunction<UIWidget>("getMarginLeft", &UIWidget::getMarginLeft);
g_lua.bindClassMemberFunction<UIWidget>("getLastFocusReason", &UIWidget::getLastFocusReason);
g_lua.bindClassMemberFunction<UIWidget>("getStyle", &UIWidget::getStyle);
g_lua.bindClassMemberFunction<UIWidget>("getChildren", &UIWidget::getChildren);
g_lua.bindClassMemberFunction<UIWidget>("getFocusedChild", &UIWidget::getFocusedChild); g_lua.bindClassMemberFunction<UIWidget>("getFocusedChild", &UIWidget::getFocusedChild);
g_lua.bindClassMemberFunction<UIWidget>("getChildAfter", &UIWidget::getChildAfter);
g_lua.bindClassMemberFunction<UIWidget>("getChildBefore", &UIWidget::getChildBefore);
g_lua.bindClassMemberFunction<UIWidget>("getChildById", &UIWidget::getChildById);
g_lua.bindClassMemberFunction<UIWidget>("getChildByPos", &UIWidget::getChildByPos);
g_lua.bindClassMemberFunction<UIWidget>("getChildByIndex", &UIWidget::getChildByIndex);
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildById", &UIWidget::recursiveGetChildById);
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildByPos", &UIWidget::recursiveGetChildByPos);
g_lua.bindClassMemberFunction<UIWidget>("backwardsGetWidgetById", &UIWidget::backwardsGetWidgetById);
g_lua.bindClassMemberFunction<UIWidget>("addChild", &UIWidget::addChild);
g_lua.bindClassMemberFunction<UIWidget>("insertChild", &UIWidget::insertChild); g_lua.bindClassMemberFunction<UIWidget>("insertChild", &UIWidget::insertChild);
g_lua.bindClassMemberFunction<UIWidget>("removeChild", &UIWidget::removeChild); g_lua.bindClassMemberFunction<UIWidget>("removeChild", &UIWidget::removeChild);
g_lua.bindClassMemberFunction<UIWidget>("hasChild", &UIWidget::hasChild);
g_lua.bindClassMemberFunction<UIWidget>("addChild", &UIWidget::addChild);
g_lua.bindClassMemberFunction<UIWidget>("focusChild", &UIWidget::focusChild); g_lua.bindClassMemberFunction<UIWidget>("focusChild", &UIWidget::focusChild);
g_lua.bindClassMemberFunction<UIWidget>("focusNextChild", &UIWidget::focusNextChild); g_lua.bindClassMemberFunction<UIWidget>("focusNextChild", &UIWidget::focusNextChild);
g_lua.bindClassMemberFunction<UIWidget>("focusPreviousChild", &UIWidget::focusPreviousChild); g_lua.bindClassMemberFunction<UIWidget>("focusPreviousChild", &UIWidget::focusPreviousChild);
g_lua.bindClassMemberFunction<UIWidget>("moveChildToTop", &UIWidget::moveChildToTop);
g_lua.bindClassMemberFunction<UIWidget>("moveChildToIndex", &UIWidget::moveChildToIndex);
g_lua.bindClassMemberFunction<UIWidget>("lockChild", &UIWidget::lockChild); g_lua.bindClassMemberFunction<UIWidget>("lockChild", &UIWidget::lockChild);
g_lua.bindClassMemberFunction<UIWidget>("unlockChild", &UIWidget::unlockChild); g_lua.bindClassMemberFunction<UIWidget>("unlockChild", &UIWidget::unlockChild);
g_lua.bindClassMemberFunction<UIWidget>("updateLayout", &UIWidget::updateLayout); g_lua.bindClassMemberFunction<UIWidget>("isChildLocked", &UIWidget::isChildLocked);
g_lua.bindClassMemberFunction<UIWidget>("getChildIndex", &UIWidget::getChildIndex);
g_lua.bindClassMemberFunction<UIWidget>("updateParentLayout", &UIWidget::updateParentLayout); g_lua.bindClassMemberFunction<UIWidget>("updateParentLayout", &UIWidget::updateParentLayout);
g_lua.bindClassMemberFunction<UIWidget>("destroy", &UIWidget::destroy); g_lua.bindClassMemberFunction<UIWidget>("updateLayout", &UIWidget::updateLayout);
g_lua.bindClassMemberFunction<UIWidget>("updateStates", &UIWidget::updateStates);
g_lua.bindClassMemberFunction<UIWidget>("updateState", &UIWidget::updateState);
g_lua.bindClassMemberFunction<UIWidget>("setState", &UIWidget::setState);
g_lua.bindClassMemberFunction<UIWidget>("hasState", &UIWidget::hasState);
g_lua.bindClassMemberFunction<UIWidget>("updateStyle", &UIWidget::updateStyle);
g_lua.bindClassMemberFunction<UIWidget>("applyStyle", &UIWidget::applyStyle);
// UILabel // UILabel
g_lua.registerClass<UILabel, UIWidget>(); g_lua.registerClass<UILabel, UIWidget>();
@ -175,12 +212,27 @@ void Application::registerLuaFunctions()
g_lua.bindClassStaticFunction<Logger>("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger)); g_lua.bindClassStaticFunction<Logger>("fireOldMessages", std::bind(&Logger::fireOldMessages, &g_logger));
g_lua.bindClassStaticFunction<Logger>("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1)); g_lua.bindClassStaticFunction<Logger>("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 // global functions
g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1)); g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1));
g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1)); g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1));
g_lua.bindGlobalFunction("setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _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("loadUI", std::bind(&UIManager::loadUI, &g_ui, _1, _2));
g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui)); 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));
} }

View File

@ -340,7 +340,7 @@ void X11Window::internalChooseGLVisual()
m_rootWindow = RootWindow(m_display, m_visual->screen); m_rootWindow = RootWindow(m_display, m_visual->screen);
#else #else
static int attrList[] = { static int attrList[] = {
EGL_BUFFER_SIZE, 16, EGL_BUFFER_SIZE, 24,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
EGL_NONE EGL_NONE
}; };

View File

@ -40,9 +40,9 @@ void UIButton::render()
if(m_icon) { if(m_icon) {
Rect iconRect; Rect iconRect;
iconRect.setSize(m_icon->getSize()); iconRect.resize(m_icon->getSize());
iconRect.moveCenter(m_rect.center()); iconRect.moveCenter(m_rect.center());
g_graphics.drawTexturedRect(iconRect, m_icon); g_painter.drawTexturedRect(iconRect, m_icon);
} }
Rect textRect = m_rect; Rect textRect = m_rect;

View File

@ -38,10 +38,10 @@ void UICheckBox::render()
{ {
if(m_image) { if(m_image) {
Rect boxRect; Rect boxRect;
boxRect.setSize(m_boxSize); boxRect.resize(m_boxSize);
boxRect.moveLeft(m_rect.left()); boxRect.moveLeft(m_rect.left());
boxRect.moveVerticalCenter(m_rect.verticalCenter()); boxRect.moveVerticalCenter(m_rect.verticalCenter());
g_graphics.bindColor(m_backgroundColor); g_painter.setColor(m_backgroundColor);
m_image->draw(boxRect); m_image->draw(boxRect);
} }

View File

@ -47,9 +47,9 @@ void UILineEdit::render()
int textLength = m_text.length(); int textLength = m_text.length();
const TexturePtr& texture = m_font->getTexture(); const TexturePtr& texture = m_font->getTexture();
g_graphics.bindColor(m_foregroundColor); g_painter.setColor(m_foregroundColor);
for(int i=0;i<textLength;++i) for(int i=0;i<textLength;++i)
g_graphics.drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]); g_painter.drawTexturedRect(m_glyphsCoords[i], texture, m_glyphsTexCoords[i]);
// render cursor // render cursor
if(isExplicitlyEnabled() && (isActive() || m_alwaysActive) && m_cursorPos >= 0) { if(isExplicitlyEnabled() && (isActive() || m_alwaysActive) && m_cursorPos >= 0) {
@ -63,7 +63,7 @@ void UILineEdit::render()
cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight()); cursorRect = Rect(m_drawArea.left()-1, m_drawArea.top(), 1, m_font->getGlyphHeight());
else else
cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight());
g_graphics.drawFilledRect(cursorRect); g_painter.drawFilledRect(cursorRect);
} else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) { } else if(g_clock.ticksElapsed(m_cursorTicks) >= 2*delay) {
m_cursorTicks = g_clock.ticks(); m_cursorTicks = g_clock.ticks();
} }

View File

@ -25,6 +25,7 @@
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
#include <framework/platform/platformwindow.h>
UIManager g_ui; UIManager g_ui;
@ -33,7 +34,7 @@ void UIManager::init()
// creates root widget // creates root widget
m_rootWidget = UIWidget::create<UIWidget>(); m_rootWidget = UIWidget::create<UIWidget>();
m_rootWidget->setId("root"); m_rootWidget->setId("root");
m_rootWidget->resize(g_graphics.getScreenSize()); m_rootWidget->resize(g_window.getSize());
} }
void UIManager::terminate() void UIManager::terminate()
@ -50,7 +51,7 @@ void UIManager::render()
void UIManager::resize(const Size& size) void UIManager::resize(const Size& size)
{ {
m_rootWidget->resize(g_graphics.getScreenSize()); m_rootWidget->resize(g_window.getSize());
} }
void UIManager::inputEvent(const InputEvent& event) void UIManager::inputEvent(const InputEvent& event)
@ -174,12 +175,15 @@ UIWidgetPtr UIManager::loadWidgetFromOTML(const OTMLNodePtr& widgetNode, const U
if(parent) if(parent)
parent->addChild(widget); parent->addChild(widget);
widget->setStyleFromNode(styleNode); if(widget) {
widget->setStyleFromNode(styleNode);
for(const OTMLNodePtr& childNode : widgetNode->children()) { for(const OTMLNodePtr& childNode : widgetNode->children()) {
if(!childNode->isUnique()) if(!childNode->isUnique())
loadWidgetFromOTML(childNode, widget); loadWidgetFromOTML(childNode, widget);
} }
} else
logError("Unable to create widget of type '", widgetType, "'");
return widget; return widget;
} }

View File

@ -35,14 +35,14 @@ void UIProgressBar::render()
{ {
UIWidget::render(); UIWidget::render();
g_graphics.bindColor(m_foregroundColor); g_painter.setColor(m_foregroundColor);
g_graphics.drawBoundingRect(m_rect, 1); g_painter.drawBoundingRect(m_rect, 1);
Rect fillRect = m_rect.expanded(-1); Rect fillRect = m_rect.expanded(-1);
fillRect.setWidth(fillRect.width() * m_percent / 100.0); fillRect.setWidth(fillRect.width() * m_percent / 100.0);
g_graphics.bindColor(m_backgroundColor); g_painter.setColor(m_backgroundColor);
g_graphics.drawFilledRect(fillRect); g_painter.drawFilledRect(fillRect);
} }
void UIProgressBar::setPercent(double percent) void UIProgressBar::setPercent(double percent)

View File

@ -69,7 +69,7 @@ void UIWidget::renderSelf()
{ {
// draw background // draw background
if(m_image) { if(m_image) {
g_graphics.bindColor(m_backgroundColor); g_painter.setColor(m_backgroundColor);
m_image->draw(m_rect); m_image->draw(m_rect);
} }
} }
@ -81,20 +81,20 @@ void UIWidget::renderChildren()
// render only visible children with a valid rect inside our rect // render only visible children with a valid rect inside our rect
if(child->isExplicitlyVisible() && child->getRect().isValid() && child->getRect().intersects(m_rect)) { if(child->isExplicitlyVisible() && child->getRect().isValid() && child->getRect().intersects(m_rect)) {
// store current graphics opacity // store current graphics opacity
int oldOpacity = g_graphics.getOpacity(); int oldOpacity = g_painter.getOpacity();
// decrease to self opacity // decrease to self opacity
if(child->getOpacity() < oldOpacity) if(child->getOpacity() < oldOpacity)
g_graphics.setOpacity(child->getOpacity()); g_painter.setOpacity(child->getOpacity());
child->render(); child->render();
// debug draw box // debug draw box
//g_graphics.bindColor(Fw::green); //g_painter.setColor(Fw::green);
//g_graphics.drawBoundingRect(child->getRect()); //g_painter.drawBoundingRect(child->getRect());
//g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red); //g_fonts.getDefaultFont()->renderText(child->getId(), child->getPosition() + Point(2, 0), Fw::red);
g_graphics.setOpacity(oldOpacity); g_painter.setOpacity(oldOpacity);
} }
} }
} }

View File

@ -78,8 +78,8 @@ public:
void setBottomLeft(const TPoint<T> &p) { x1 = p.x; y2 = p.y; } void setBottomLeft(const TPoint<T> &p) { x1 = p.x; y2 = p.y; }
void setWidth(T width) { x2 = x1 + width - 1; } void setWidth(T width) { x2 = x1 + width - 1; }
void setHeight(T height) { y2 = y1 + height- 1; } void setHeight(T height) { y2 = y1 + height- 1; }
void setSize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; } void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; }
void setSize(const TSize<T>& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; } void resize(const TSize<T>& 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 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; } void setCoords(int left, int top, int right, int bottom) { x1 = left; y1 = top; x2 = right; y2 = bottom; }

View File

@ -43,7 +43,7 @@ public:
int width() const { return wd; } int width() const { return wd; }
int height() const { return ht; } 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 setWidth(T w) { wd = w; }
void setHeight(T h) { ht = h; } void setHeight(T h) { ht = h; }
@ -115,7 +115,7 @@ std::istream& operator>>(std::istream& in, TSize<T>& size)
{ {
T w, h; T w, h;
in >> w >> h; in >> w >> h;
size.setSize(w, h); size.resize(w, h);
return in; return in;
} }

View File

@ -30,6 +30,8 @@
#include <sstream> #include <sstream>
#include <exception> #include <exception>
#include <cxxabi.h> #include <cxxabi.h>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "types.h" #include "types.h"
#include "exception.h" #include "exception.h"
@ -258,6 +260,16 @@ inline std::string ip2str(uint32 ip) {
return std::string(host); return std::string(host);
} }
template<typename T = std::string>
std::vector<T> split(const std::string& str, const std::string& separators = " ") {
std::vector<std::string> splitted;
boost::split(splitted, str, boost::is_any_of(std::string(separators)));
std::vector<T> results(splitted.size());
for(uint i=0;i<splitted.size();++i)
results[i] = Fw::safeCast<T>(splitted[i]);
return results;
}
template<typename... T> template<typename... T>
void throwException(const T&... args) { void throwException(const T&... args) {
throw Exception(Fw::mkstr(args...)); throw Exception(Fw::mkstr(args...));

View File

@ -25,9 +25,9 @@
int main(int argc, const char* argv[]) int main(int argc, const char* argv[])
{ {
std::vector<std::string> args(argv, argv + argc); std::vector<std::string> args(argv, argv + argc);
OTClient otclient; OTClient app;
otclient.init(args); app.init(args);
otclient.run(); app.run();
otclient.terminate(); app.terminate();
return 0; return 0;
} }

View File

@ -47,8 +47,8 @@ void Creature::draw(const Point& p)
{ {
// TODO: activate on attack, follow, discover how 'attacked' works // TODO: activate on attack, follow, discover how 'attacked' works
if(m_showSquareColor) { if(m_showSquareColor) {
g_graphics.bindColor(Outfit::getColor(m_squareColor)); g_painter.setColor(Outfit::getColor(m_squareColor));
g_graphics.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2); g_painter.drawBoundingRect(Rect(p + m_walkOffset - 8, Size(32, 32)), 2);
} }
// Render creature // Render creature
@ -59,33 +59,33 @@ void Creature::draw(const Point& p)
continue; continue;
// draw white item // draw white item
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
internalDraw(p + m_walkOffset, 0); internalDraw(p + m_walkOffset, 0);
// draw mask if exists // draw mask if exists
if(m_type->dimensions[ThingType::Layers] > 1) { if(m_type->dimensions[ThingType::Layers] > 1) {
// switch to blend color mode // switch to blend color mode
g_graphics.bindBlendFunc(Fw::BlendColorzing); g_painter.setCompositionMode(Painter::CompositionMode_ColorizeDest);
// head // head
g_graphics.bindColor(m_outfit.getHeadColor()); g_painter.setColor(m_outfit.getHeadColor());
internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask); internalDraw(p + m_walkOffset, 1, Otc::SpriteYellowMask);
// body // body
g_graphics.bindColor(m_outfit.getBodyColor()); g_painter.setColor(m_outfit.getBodyColor());
internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask); internalDraw(p + m_walkOffset, 1, Otc::SpriteRedMask);
// legs // legs
g_graphics.bindColor(m_outfit.getLegsColor()); g_painter.setColor(m_outfit.getLegsColor());
internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask); internalDraw(p + m_walkOffset, 1, Otc::SpriteGreenMask);
// feet // feet
g_graphics.bindColor(m_outfit.getFeetColor()); g_painter.setColor(m_outfit.getFeetColor());
internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask); internalDraw(p + m_walkOffset, 1, Otc::SpriteBlueMask);
// restore default blend func // restore default blend func
g_graphics.bindBlendFunc(Fw::BlendDefault); g_painter.setCompositionMode(Painter::CompositionMode_SourceOver);
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
} }
} }
} }
@ -115,11 +115,11 @@ void Creature::drawInformation(int x, int y, bool useGray, const Rect& rect)
healthRect.setWidth((m_healthPercent / 100.0) * 25); healthRect.setWidth((m_healthPercent / 100.0) * 25);
// draw // draw
g_graphics.bindColor(Fw::black); g_painter.setColor(Fw::black);
g_graphics.drawFilledRect(backgroundRect); g_painter.drawFilledRect(backgroundRect);
g_graphics.bindColor(fillColor); g_painter.setColor(fillColor);
g_graphics.drawFilledRect(healthRect); g_painter.drawFilledRect(healthRect);
m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor); m_informationFont->renderText(m_name, textRect, Fw::AlignTopCenter, fillColor);
} }

View File

@ -41,7 +41,7 @@ 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)); m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS));
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
m_framebuffer->bind(); m_framebuffer->bind();
// draw offsets // draw offsets
@ -80,9 +80,9 @@ void Map::draw(const Rect& rect)
} }
} }
m_framebuffer->unbind(); m_framebuffer->release();
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
m_framebuffer->draw(rect); m_framebuffer->draw(rect);
// calculate stretch factor // calculate stretch factor

View File

@ -55,7 +55,7 @@ void Thing::internalDraw(const Point& p, int layers, Otc::SpriteMask mask)
Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX], Rect drawRect((p.x - xi*32) - m_type->parameters[ThingType::DisplacementX],
(p.y - yi*32) - m_type->parameters[ThingType::DisplacementY], (p.y - yi*32) - m_type->parameters[ThingType::DisplacementY],
32, 32); 32, 32);
g_graphics.drawTexturedRect(drawRect, spriteTex); g_painter.drawTexturedRect(drawRect, spriteTex);
} }
} }
} }

View File

@ -36,6 +36,5 @@ void OTClient::init(const std::vector<std::string>& args)
g_modules.discoverModules(); g_modules.discoverModules();
g_modules.autoLoadModules(100); g_modules.autoLoadModules(100);
g_modules.ensureModuleLoaded("client"); g_modules.ensureModuleLoaded("client");
g_modules.ensureModuleLoaded("game");
g_modules.autoLoadModules(1000); g_modules.autoLoadModules(1000);
} }

View File

@ -34,7 +34,7 @@ void UICreature::render()
renderSelf(); renderSelf();
if(m_creature) { if(m_creature) {
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
m_creature->draw(m_rect.bottomRight() - Point(32, 32) + m_creatureMargin); m_creature->draw(m_rect.bottomRight() - Point(32, 32) + m_creatureMargin);
} }

View File

@ -34,7 +34,7 @@ void UIItem::render()
renderSelf(); renderSelf();
if(m_item) { if(m_item) {
g_graphics.bindColor(Fw::white); g_painter.setColor(Fw::white);
m_item->draw(m_rect.bottomRight() - Point(32, 32) + m_itemMargin); m_item->draw(m_rect.bottomRight() - Point(32, 32) + m_itemMargin);
} }

View File

@ -35,8 +35,8 @@ void UIMap::render()
{ {
renderSelf(); renderSelf();
g_graphics.bindColor(Fw::black); g_painter.setColor(Fw::black);
g_graphics.drawBoundingRect(m_mapRect.expanded(1)); g_painter.drawBoundingRect(m_mapRect.expanded(1));
g_map.draw(m_mapRect); g_map.draw(m_mapRect);
renderChildren(); 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); Size mapSize(g_map.getVibibleSize().width() * Map::NUM_TILE_PIXELS, g_map.getVibibleSize().height() * Map::NUM_TILE_PIXELS);
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio); mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
m_mapRect.setSize(mapSize); m_mapRect.resize(mapSize);
m_mapRect.moveCenter(newRect.center()); m_mapRect.moveCenter(newRect.center());
} }

View File

@ -15,16 +15,16 @@ if not io.open(cppclassheader, 'r') then
return false return false
end end
function string.matchcount(str, pattern) function string:matchcount(pattern)
local count = 0 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 return count
end end
function string.splitlines(str) function string:splitlines()
local t = {} local t = {}
local function helper(line) table.insert(t, line) return "" end local function helper(line) table.insert(t, line) return "" end
helper((str:gsub("(.-)\r?\n", helper))) helper((self:gsub("(.-)\r?\n", helper)))
return t return t
end end
@ -34,7 +34,7 @@ for line in io.lines(cppclassheader) do
foundclassname = line:match('^class ([%w_]+)') foundclassname = line:match('^class ([%w_]+)')
if foundclassname then if foundclassname then
if not cppclassname then if not cppclassname then
guessedclassname = cppclassheader:match('([%w_]+).h'):lower() guessedclassname = cppclassheader:match('([%w_]+)\.h$'):lower()
if foundclassname:lower() == guessedclassname then if foundclassname:lower() == guessedclassname then
cppclassname = foundclassname cppclassname = foundclassname
end end
@ -69,8 +69,9 @@ for line in io.lines(cppclassheader) do
elseif line:match('private:') or line:match('protected:') then elseif line:match('private:') or line:match('protected:') then
publicmethods = false publicmethods = false
elseif publicmethods then elseif publicmethods then
for funcname,args in line:gmatch(' *[%w :_]* ([%w_]+)%(([^%(]*%)) *[;{].*$') do funcname, args = line:match('^ *[%w <>&\*:_]* ([%w_]+)%(([^%)]*%))[%w ]*[;{].*$')
if funcname ~= cppclassname then if funcname then
if funcname ~= cppclassname and funcname ~= 'create' then
numargs = args:matchcount('[^,)]+[,)]') numargs = args:matchcount('[^,)]+[,)]')
if cppclassinstance then if cppclassinstance then