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

6
TODO
View File

@ -14,11 +14,10 @@ fix moving windows and tooltips conflicts
todo display otclient icon in window bar
remake otui styles states system
padding
break UILabel lines
rename Game to g_game, etc
implement Console key binding
fatal error if sprite load fails
impl vertical sync, clipboard
crash handler
modify COnnection::poll()
@ -30,3 +29,6 @@ use metatable for Point,Rect,Color,Size lua classes
lua binder generator
restore win32 platform
set special types for g_configs like lists/point/size
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()
if cursorPos == 0 then return end
local commandBegin = string.sub(commandLineEdit:getText(), 1, cursorPos)
local commandBegin = commandLineEdit:getText():sub(1, cursorPos)
local possibleCommands = {}
-- create a list containing all globals
@ -43,7 +43,7 @@ local function completeCommand()
-- match commands
for k,v in pairs(allVars) do
if string.sub(k, 1, cursorPos) == commandBegin then
if k:sub(1, cursorPos) == commandBegin then
table.insert(possibleCommands, k)
end
end
@ -63,9 +63,9 @@ local function completeCommand()
if #possibleCommands[1] < cursorPos then
break
end
expandedComplete = commandBegin .. string.sub(possibleCommands[1], cursorPos, cursorPos)
expandedComplete = commandBegin .. possibleCommands[1]:sub(cursorPos, cursorPos)
for i,v in ipairs(possibleCommands) do
if string.sub(v, 1, #expandedComplete) ~= expandedComplete then
if v:sub(1, #expandedComplete) ~= expandedComplete then
done = true
end
end

View File

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

View File

@ -3,7 +3,7 @@ Client = { }
-- TODO: load and save configurations
function Client.init()
g_window.move({ x=220, y=220 })
g_window.resize({ width=800, height=600 })
g_window.resize({ width=800, height=480 })
g_window.setTitle('OTClient')
g_window.setIcon('clienticon.png')
return true

View File

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

View File

@ -7,7 +7,7 @@ local vsyncEnabled = false
function getConfig(name, default)
if g_configs.exists(name) then
local val = string.trim(g_configs.get(name))
local val = g_configs.get(name):trim()
if val == 'true' or val == 'false' then
return toboolean(val)
else

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -135,6 +135,7 @@ SET(framework_SOURCES ${framework_SOURCES}
${CMAKE_CURRENT_LIST_DIR}/graphics/font.cpp
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.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/framebuffer.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/borderimage.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
${CMAKE_CURRENT_LIST_DIR}/otml/otmldocument.cpp

View File

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

View File

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

View File

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

View File

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

View File

@ -32,6 +32,9 @@ class Font;
class Image;
class BorderImage;
class FrameBuffer;
class Shader;
class ShaderProgram;
class PainterShaderProgram;
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<BorderImage> BorderImagePtr;
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

View File

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

View File

@ -26,110 +26,52 @@
FrameBuffer::FrameBuffer(int width, int height)
{
m_fbo = 0;
// create FBO texture
m_texture = TexturePtr(new Texture(width, height, 4));
m_texture->enableBilinearFilter();
// use FBO ext only if supported
if(g_graphics.isExtensionSupported("GL_ARB_framebuffer_object")) {
m_fallbackOldImp = false;
// generate FBO
glGenFramebuffers(1, &m_fbo);
if(!m_fbo)
logFatal("Unable to create framebuffer object");
// generate FBO
glGenFramebuffers(1, &m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
// attach 2D texture to this FBO
glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, m_texture->getId(), 0);
// attach 2D texture to this FBO
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture->getId(), 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_FRAMEBUFFER_COMPLETE_EXT:
//ok
break;
default: // fallback to old implementation
m_fallbackOldImp = true;
break;
}
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if(status != GL_FRAMEBUFFER_COMPLETE)
logFatal("Unable to create framebuffer object");
// restore back buffer
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
} else {
// otherwise fallback to copy texture from screen implementation
m_fallbackOldImp = true;
}
if(m_fallbackOldImp)
logInfo("Framebuffers not supported, falling back to old implementation.");
// restore back buffer
glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
FrameBuffer::~FrameBuffer()
{
if(m_fbo)
glDeleteFramebuffers(1, &m_fbo);
glDeleteFramebuffers(1, &m_fbo);
}
void FrameBuffer::bind()
{
if(!m_fallbackOldImp) {
// bind framebuffer
glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
} else {
int screenWidth = g_graphics.getScreenSize().width();
int screenHeight = g_graphics.getScreenSize().height();
if(!m_screenBackup || m_screenBackup->getSize() != g_graphics.getScreenSize())
m_screenBackup = TexturePtr(new Texture(screenWidth, screenHeight, 4));
// save screen state
glBindTexture(GL_TEXTURE_2D, m_screenBackup->getId());
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, screenWidth, screenHeight);
}
// setup framebuffer viewport
glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight());
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, m_texture->getWidth(), m_texture->getHeight(), 0, -1, 1);
// back to model view
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// clear framebuffer
glClearColor(0.0, 0.0, 0.0, 1.0);
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, m_texture->getWidth(), m_texture->getHeight());
g_painter.updateProjectionMatrix(m_texture->getSize(), true);
}
void FrameBuffer::unbind()
void FrameBuffer::release()
{
if(!m_fallbackOldImp) {
// bind back buffer again
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
glDrawBuffer(GL_BACK);
glReadBuffer(GL_BACK);
// bind back buffer again
glBindFramebuffer(GL_FRAMEBUFFER, 0);
// restore graphics viewport
g_graphics.restoreViewport();
} else {
// copy screen to texture
glBindTexture(GL_TEXTURE_2D, m_texture->getId());
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, m_texture->getWidth(), m_texture->getHeight());
// restore graphics viewport
g_graphics.restoreViewport();
// restore screen
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
g_graphics.drawTexturedRect(Rect(Point(0,0), g_graphics.getScreenSize()), m_screenBackup, Rect(), true);
}
// restore graphics viewport
glViewport(0, 0, g_graphics.getViewportSize().width(), g_graphics.getViewportSize().height());
g_painter.updateProjectionMatrix(g_graphics.getViewportSize());
}
void FrameBuffer::draw(const Rect& screenCoords, const Rect& framebufferCoords)
void FrameBuffer::draw(const Rect& dest)
{
g_graphics.drawTexturedRect(screenCoords, m_texture, framebufferCoords, true);
g_painter.drawTexturedRect(dest, m_texture);
}

View File

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

View File

@ -30,307 +30,48 @@ Graphics g_graphics;
void Graphics::init()
{
// setup opengl
glEnable(GL_ALPHA_TEST); // enable alpha by default
glAlphaFunc(GL_GREATER, 0.0f); // default alpha func
glDisable(GL_DEPTH_TEST); // we are rendering 2D only, we don't need depth buffer
glEnable(GL_TEXTURE_2D); // enable textures by default
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
glShadeModel(GL_SMOOTH);
glEnable(GL_BLEND);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
logInfo("GPU ", glGetString(GL_RENDERER));
logInfo("OpenGL ", glGetString(GL_VERSION));
m_drawing = false;
m_opacity = 255;
//if(!isExtensionSupported("GL_ARB_framebuffer_object"))
// logFatal("Your graphics card is not supported.");
m_emptyTexture = TexturePtr(new Texture);
bindColor(Fw::white);
bindBlendFunc(Fw::BlendDefault);
g_painter.init();
}
void Graphics::terminate()
{
g_fonts.releaseFonts();
g_painter.terminate();
m_emptyTexture.reset();
}
bool Graphics::isExtensionSupported(const char *extension)
{
const GLubyte *extensions = NULL;
const GLubyte *start;
GLubyte *where, *terminator;
where = (GLubyte *)strchr(extension, ' ');
if(where || *extension == '\0')
return 0;
extensions = glGetString(GL_EXTENSIONS);
start = extensions;
while(true) {
where = (GLubyte *) strstr((const char *)start, extension);
if(!where)
break;
terminator = where + strlen(extension);
if(where == start || *(where - 1) == ' ')
if(*terminator == ' ' || *terminator == '\0')
return 1;
start = terminator;
}
return 0;
std::string extensionsString = (const char*)glGetString(GL_EXTENSIONS);
auto extensions = Fw::split(extensionsString);
return std::find(extensions.begin(), extensions.end(), extension) != extensions.end();
}
void Graphics::resize(const Size& size)
{
m_screenSize = size;
restoreViewport();
}
void Graphics::restoreViewport()
{
const int& width = m_screenSize.width();
const int& height = m_screenSize.height();
// resize gl viewport
glViewport(0, 0, width, height);
/*
0,0---------0,w
| |
| |
| |
h,0---------h,w
*/
// setup view region like above
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0f, width, height, 0.0f, -1, 1);
// back to model view
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, size.width(), size.height());
g_painter.updateProjectionMatrix(size);
m_viewportSize = size;
}
void Graphics::beginRender()
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
}
void Graphics::endRender()
{
assert(!m_drawing);
}
void Graphics::drawTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords,
bool upsideDown)
{
if(screenCoords.isEmpty() || texture->getId() == 0)
return;
// rect correction for opengl
int right = screenCoords.right() + 1;
int bottom = screenCoords.bottom() + 1;
int top = screenCoords.top();
int left = screenCoords.left();
float textureRight;
float textureBottom;
float textureTop;
float textureLeft;
const Size& textureSize = texture->getGlSize();
if(textureCoords.isEmpty()) {
textureRight = texture->getWidth() / (float)textureSize.width();
if(upsideDown) {
textureBottom = 0.0f;
textureTop = texture->getHeight() / (float)textureSize.height();
} else {
textureBottom = texture->getHeight() / (float)textureSize.height();
textureTop = 0.0f;
}
textureLeft = 0.0f;
} else {
textureRight = (textureCoords.right() + 1) / (float)textureSize.width();
if(upsideDown) {
textureTop = (textureCoords.bottom() + 1) / (float)textureSize.height();
textureBottom = textureCoords.top() / (float)textureSize.height();
} else {
textureBottom = (textureCoords.bottom() + 1) / (float)textureSize.height();
textureTop = textureCoords.top() / (float)textureSize.height();
}
textureLeft = textureCoords.left() / (float)textureSize.width();
}
if(!m_drawing) {
bindTexture(texture);
glBegin(GL_QUADS);
}
glTexCoord2f(textureLeft, textureTop); glVertex2i(left, top);
glTexCoord2f(textureLeft, textureBottom); glVertex2i(left, bottom);
glTexCoord2f(textureRight, textureBottom); glVertex2i(right, bottom);
glTexCoord2f(textureRight, textureTop); glVertex2i(right, top);
if(!m_drawing)
glEnd();
}
void Graphics::drawRepeatedTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords)
{
if(screenCoords.isEmpty() || texture->getId() == 0 || textureCoords.isEmpty())
return;
bool mustStopDrawing = false;
if(!m_drawing) {
bindTexture(texture);
startDrawing();
mustStopDrawing = true;
}
// render many repeated texture rects
Rect virtualScreenCoords(0,0,screenCoords.size());
for(int y = 0; y <= virtualScreenCoords.height(); y += textureCoords.height()) {
for(int x = 0; x <= virtualScreenCoords.width(); x += textureCoords.width()) {
Rect partialCoords(x, y, textureCoords.size());
Rect partialTextureCoords = textureCoords;
// partialCoords to screenCoords bottomRight
if(partialCoords.bottom() > virtualScreenCoords.bottom()) {
partialTextureCoords.setBottom(partialTextureCoords.bottom() +
(virtualScreenCoords.bottom() - partialCoords.bottom()));
partialCoords.setBottom(virtualScreenCoords.bottom());
}
if(partialCoords.right() > virtualScreenCoords.right()) {
partialTextureCoords.setRight(partialTextureCoords.right() +
(virtualScreenCoords.right() - partialCoords.right()));
partialCoords.setRight(virtualScreenCoords.right());
}
partialCoords.translate(screenCoords.topLeft());
drawTexturedRect(partialCoords, texture, partialTextureCoords);
}
}
if(mustStopDrawing)
stopDrawing();
}
void Graphics::drawFilledRect(const Rect& screenCoords)
{
assert(!m_drawing);
if(screenCoords.isEmpty())
return;
// rect correction for opengl
int right = screenCoords.right() + 1;
int bottom = screenCoords.bottom() + 1;
int top = screenCoords.top();
int left = screenCoords.left();
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
glVertex2i(left, top);
glVertex2i(left, bottom);
glVertex2i(right, bottom);
glVertex2i(right, top);
glEnd();
glEnable(GL_TEXTURE_2D);
}
void Graphics::drawBoundingRect(const Rect& screenCoords,
int innerLineWidth)
{
assert(!m_drawing);
if(screenCoords.isEmpty() || 2 * innerLineWidth > screenCoords.height())
return;
// rect correction for opengl
int right = screenCoords.right()+1;
int bottom = screenCoords.bottom()+1;
int top = screenCoords.top();
int left = screenCoords.left();
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
// top line
glVertex2i(left, top);
glVertex2i(left, top + innerLineWidth);
glVertex2i(right, top + innerLineWidth);
glVertex2i(right, top);
// left
glVertex2i(left, screenCoords.top() + innerLineWidth);
glVertex2i(left, bottom - innerLineWidth);
glVertex2i(left + innerLineWidth, bottom - innerLineWidth);
glVertex2i(left + innerLineWidth, screenCoords.top() + innerLineWidth);
// bottom line
glVertex2i(left, bottom);
glVertex2i(left, bottom - innerLineWidth);
glVertex2i(right, bottom - innerLineWidth);
glVertex2i(right, bottom);
// right line
glVertex2i(right , top + innerLineWidth);
glVertex2i(right , bottom - innerLineWidth);
glVertex2i(right - innerLineWidth, bottom - innerLineWidth);
glVertex2i(right - innerLineWidth, top + innerLineWidth);
glEnd();
glEnable(GL_TEXTURE_2D);
}
void Graphics::bindColor(const Color& color)
{
Color tmp = color;
tmp.setAlpha(std::min((uint8)m_opacity, color.a()));
glColor4ubv(tmp.rgbaPtr());
}
void Graphics::bindTexture(const TexturePtr& texture)
{
glBindTexture(GL_TEXTURE_2D, texture->getId());
}
void Graphics::bindBlendFunc(Fw::BlendFunc blendType)
{
switch(blendType) {
case Fw::BlendDefault:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case Fw::BlendColorzing:
glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA);
break;
}
}
void Graphics::startDrawing()
{
assert(!m_drawing);
glBegin(GL_QUADS);
m_drawing = true;
}
void Graphics::stopDrawing()
{
assert(m_drawing);
glEnd();
m_drawing = false;
glFlush();
}

View File

@ -24,64 +24,25 @@
#define GRAPHICS_H
#include "declarations.h"
#include "painter.h"
class Graphics
{
public:
/// Initialize default OpenGL states
void init();
/// Termiante graphics
void terminate();
/// Check if a GL extension is supported
bool isExtensionSupported(const char *extension);
/// Resizes OpenGL viewport
void resize(const Size& size);
/// Restore original viewport
void restoreViewport();
/// Called before every render
void beginRender();
/// Called after every render
void endRender();
void bindColor(const Color& color);
void bindTexture(const TexturePtr& texture);
void bindBlendFunc(Fw::BlendFunc blendType);
// drawing API
void drawTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords = Rect(),
bool upsideDown = false);
void drawRepeatedTexturedRect(const Rect& screenCoords,
const TexturePtr& texture,
const Rect& textureCoords);
void drawFilledRect(const Rect& screenCoords);
void drawBoundingRect(const Rect& screenCoords,
int innerLineWidth = 1);
const Size& getScreenSize() const { return m_screenSize; }
void startDrawing();
void stopDrawing();
bool isDrawing() const { return m_drawing; }
int getOpacity() const { return m_opacity; }
void setOpacity(int opacity) { m_opacity = opacity; }
const Size& getViewportSize() const { return m_viewportSize; }
TexturePtr getEmptyTexture() { return m_emptyTexture; }
private:
bool m_drawing;
int m_opacity;
Size m_screenSize;
Size m_viewportSize;
TexturePtr m_emptyTexture;
};

View File

@ -63,12 +63,12 @@ void Image::draw(const Rect& screenCoords)
else if(texSize.width() > texCoordsSize.width())
texCoordsOffset.x = (texSize.width() - texCoordsSize.width())/2;
g_graphics.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize));
g_painter.drawTexturedRect(screenCoords, m_texture, Rect(texCoordsOffset, texCoordsSize));
} else {
if(m_repeated)
g_graphics.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords);
g_painter.drawRepeatedTexturedRect(screenCoords, m_texture, m_textureCoords);
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()
{
assert(!g_graphics.isDrawing());
// free texture from gl memory
if(m_textureId > 0)
glDeleteTextures(1, &m_textureId);
@ -44,9 +43,7 @@ Texture::~Texture()
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height)
{
assert(!g_graphics.isDrawing());
m_size.setSize(width, height);
m_size.resize(width, height);
// gets max texture size supported by the driver
static GLint maxTexSize = -1;
@ -70,7 +67,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
std::vector<uint8> tmp;
// old opengl drivers only accept power of two dimensions
//if(!g_graphics.isExtensionSupported("GL_ARB_texture_non_power_of_two")) {
//if(!g_painter.isExtensionSupported("GL_ARB_texture_non_power_of_two")) {
int glWidth = 1;
while(glWidth < width)
glWidth = glWidth << 1;
@ -88,7 +85,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
pixels = &tmp[0];
}
m_glSize.setSize(glWidth, glHeight);
m_glSize.resize(glWidth, glHeight);
//} else
// m_glSize = m_size;
@ -110,7 +107,7 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
}
// load pixels into gl memory
glTexImage2D(GL_TEXTURE_2D, 0, channels, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
// disable texture border
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@ -119,7 +116,6 @@ uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int
// nearest filtering (non smooth)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
return id;
}

View File

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

View File

@ -36,73 +36,110 @@ void Application::registerLuaFunctions()
// UIWidget
g_lua.registerClass<UIWidget>();
g_lua.bindClassStaticFunction<UIWidget>("create", &UIWidget::create<UIWidget>);
g_lua.bindClassMemberFunction<UIWidget>("getId", &UIWidget::getId);
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>("destroy", &UIWidget::destroy);
g_lua.bindClassMemberFunction<UIWidget>("setVisible", &UIWidget::setVisible);
g_lua.bindClassMemberFunction<UIWidget>("getWidth", &UIWidget::getWidth);
g_lua.bindClassMemberFunction<UIWidget>("setWidth", &UIWidget::setWidth);
g_lua.bindClassMemberFunction<UIWidget>("getHeight", &UIWidget::getHeight);
g_lua.bindClassMemberFunction<UIWidget>("setHeight", &UIWidget::setHeight);
g_lua.bindClassMemberFunction<UIWidget>("getSize", &UIWidget::getSize);
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>("setEnabled", &UIWidget::setEnabled);
g_lua.bindClassMemberFunction<UIWidget>("setPressed", &UIWidget::setPressed);
g_lua.bindClassMemberFunction<UIWidget>("setId", &UIWidget::setId);
g_lua.bindClassMemberFunction<UIWidget>("setFocusable", &UIWidget::setFocusable);
g_lua.bindClassMemberFunction<UIWidget>("setPhantom", &UIWidget::setPhantom);
g_lua.bindClassMemberFunction<UIWidget>("setStyle", &UIWidget::setStyle);
g_lua.bindClassMemberFunction<UIWidget>("applyStyle", &UIWidget::applyStyle);
g_lua.bindClassMemberFunction<UIWidget>("getStyle", &UIWidget::getStyle);
g_lua.bindClassMemberFunction<UIWidget>("getMarginTop", &UIWidget::getMarginTop);
g_lua.bindClassMemberFunction<UIWidget>("setStyleFromNode", &UIWidget::setStyleFromNode);
//g_lua.bindClassMemberFunction<UIWidget>("setLayout", &UIWidget::setLayout);
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>("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>("isVisible", &UIWidget::isVisible);
g_lua.bindClassMemberFunction<UIWidget>("isHidden", &UIWidget::isHidden);
g_lua.bindClassMemberFunction<UIWidget>("isHovered", &UIWidget::isHovered);
g_lua.bindClassMemberFunction<UIWidget>("isFocused", &UIWidget::isFocused);
g_lua.bindClassMemberFunction<UIWidget>("isPressed", &UIWidget::isPressed);
g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled);
g_lua.bindClassMemberFunction<UIWidget>("isDisabled", &UIWidget::isDisabled);
g_lua.bindClassMemberFunction<UIWidget>("isActive", &UIWidget::isActive);
g_lua.bindClassMemberFunction<UIWidget>("setMarginBottom", &UIWidget::setMarginBottom);
g_lua.bindClassMemberFunction<UIWidget>("setMarginLeft", &UIWidget::setMarginLeft);
g_lua.bindClassMemberFunction<UIWidget>("setSizeFixed", &UIWidget::setSizeFixed);
g_lua.bindClassMemberFunction<UIWidget>("setLastFocusReason", &UIWidget::setLastFocusReason);
g_lua.bindClassMemberFunction<UIWidget>("resize", &UIWidget::resize);
g_lua.bindClassMemberFunction<UIWidget>("moveTo", &UIWidget::moveTo);
g_lua.bindClassMemberFunction<UIWidget>("hide", &UIWidget::hide);
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>("unlock", &UIWidget::unlock);
g_lua.bindClassMemberFunction<UIWidget>("focus", &UIWidget::focus);
g_lua.bindClassMemberFunction<UIWidget>("getChildren", &UIWidget::getChildren);
g_lua.bindClassMemberFunction<UIWidget>("recursiveGetChildById", &UIWidget::recursiveGetChildById);
g_lua.bindClassMemberFunction<UIWidget>("getChildById", &UIWidget::getChildById);
g_lua.bindClassMemberFunction<UIWidget>("getChildByIndex", &UIWidget::getChildByIndex);
g_lua.bindClassMemberFunction<UIWidget>("isActive", &UIWidget::isActive);
g_lua.bindClassMemberFunction<UIWidget>("isEnabled", &UIWidget::isEnabled);
g_lua.bindClassMemberFunction<UIWidget>("isDisabled", &UIWidget::isDisabled);
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>("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>("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>("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>("focusNextChild", &UIWidget::focusNextChild);
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>("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>("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
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>("setOnLog", std::bind(&Logger::setOnLog, &g_logger, _1));
// Font
/*
// FontManager
g_lua.registerStaticClass("g_fonts");
g_lua.bindClassStaticFunction("g_fonts", "releaseFonts", std::bind(&FontManager::releaseFonts, &g_fonts));
g_lua.bindClassStaticFunction("g_fonts", "importFont", std::bind(&FontManager::importFont, &g_fonts, _1));
g_lua.bindClassStaticFunction("g_fonts", "fontExists", std::bind(&FontManager::fontExists, &g_fonts, _1));
g_lua.bindClassStaticFunction("g_fonts", "getFont", std::bind(&FontManager::getFont, &g_fonts, _1));
g_lua.bindClassStaticFunction("g_fonts", "getDefaultFont", std::bind(&FontManager::getDefaultFont, &g_fonts));
g_lua.bindClassStaticFunction("g_fonts", "setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1));
*/
g_lua.registerStaticClass("g_dispatcher");
g_lua.bindClassStaticFunction("g_dispatcher", "addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, _2));
g_lua.bindClassStaticFunction("g_dispatcher", "scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2));
// global functions
g_lua.bindGlobalFunction("importFont", std::bind(&FontManager::importFont, &g_fonts, _1));
g_lua.bindGlobalFunction("importStyles", std::bind(&UIManager::importStyles, &g_ui, _1));
g_lua.bindGlobalFunction("setDefaultFont", std::bind(&FontManager::setDefaultFont, &g_fonts, _1));
g_lua.bindGlobalFunction("loadUI", std::bind(&UIManager::loadUI, &g_ui, _1, _2));
g_lua.bindGlobalFunction("getRootWidget", std::bind(&UIManager::getRootWidget, &g_ui));
g_lua.bindGlobalFunction("addEvent", std::bind(&EventDispatcher::addEvent, &g_dispatcher, _1, false));
g_lua.bindGlobalFunction("scheduleEvent", std::bind(&EventDispatcher::scheduleEvent, &g_dispatcher, _1, _2));
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -78,8 +78,8 @@ public:
void setBottomLeft(const TPoint<T> &p) { x1 = p.x; y2 = p.y; }
void setWidth(T width) { x2 = x1 + width - 1; }
void setHeight(T height) { y2 = y1 + height- 1; }
void setSize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; }
void setSize(const TSize<T>& size) { x2 = x1 + size.width() - 1; y2 = y1 + size.height() - 1; }
void resize(T width, T height) { x2 = x1 + width - 1; y2 = y1 + height - 1; }
void resize(const TSize<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 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 height() const { return ht; }
void setSize(T w, T h) { wd = w; ht = h; }
void resize(T w, T h) { wd = w; ht = h; }
void setWidth(T w) { wd = w; }
void setHeight(T h) { ht = h; }
@ -115,7 +115,7 @@ std::istream& operator>>(std::istream& in, TSize<T>& size)
{
T w, h;
in >> w >> h;
size.setSize(w, h);
size.resize(w, h);
return in;
}

View File

@ -30,6 +30,8 @@
#include <sstream>
#include <exception>
#include <cxxabi.h>
#include <vector>
#include <boost/algorithm/string.hpp>
#include "types.h"
#include "exception.h"
@ -258,6 +260,16 @@ inline std::string ip2str(uint32 ip) {
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>
void throwException(const T&... args) {
throw Exception(Fw::mkstr(args...));

View File

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

View File

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

View File

@ -41,7 +41,7 @@ void Map::draw(const Rect& rect)
if(!m_framebuffer)
m_framebuffer = FrameBufferPtr(new FrameBuffer(m_visibleSize.width() * NUM_TILE_PIXELS, m_visibleSize.height() * NUM_TILE_PIXELS));
g_graphics.bindColor(Fw::white);
g_painter.setColor(Fw::white);
m_framebuffer->bind();
// 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);
// 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],
(p.y - yi*32) - m_type->parameters[ThingType::DisplacementY],
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.autoLoadModules(100);
g_modules.ensureModuleLoaded("client");
g_modules.ensureModuleLoaded("game");
g_modules.autoLoadModules(1000);
}

View File

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

View File

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

View File

@ -35,8 +35,8 @@ void UIMap::render()
{
renderSelf();
g_graphics.bindColor(Fw::black);
g_graphics.drawBoundingRect(m_mapRect.expanded(1));
g_painter.setColor(Fw::black);
g_painter.drawBoundingRect(m_mapRect.expanded(1));
g_map.draw(m_mapRect);
renderChildren();
@ -78,6 +78,6 @@ void UIMap::onGeometryUpdate(const Rect& oldRect, const Rect& newRect)
Size mapSize(g_map.getVibibleSize().width() * Map::NUM_TILE_PIXELS, g_map.getVibibleSize().height() * Map::NUM_TILE_PIXELS);
mapSize.scale(mapRect.size(), Fw::KeepAspectRatio);
m_mapRect.setSize(mapSize);
m_mapRect.resize(mapSize);
m_mapRect.moveCenter(newRect.center());
}

View File

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