graphics fixes and improvements

This commit is contained in:
Eduardo Bart 2012-06-08 13:58:08 -03:00
parent 4f9ca15ef0
commit 1a7f2a44fc
39 changed files with 450 additions and 317 deletions

View File

@ -43,7 +43,6 @@ locale = {
["Auto login"] = "Entrar automaticamente", ["Auto login"] = "Entrar automaticamente",
["Auto login selected character on next charlist load"] = "Entrar automaticamente com o personagem quando reabrir a lista de personagens", ["Auto login selected character on next charlist load"] = "Entrar automaticamente com o personagem quando reabrir a lista de personagens",
["Axe Fighting"] = "Combate com Machado", ["Axe Fighting"] = "Combate com Machado",
["Background pane framerate limit: %s"] = "Limite da taxa de quadros no segundo plano: %s",
["Banishment"] = "Banimento", ["Banishment"] = "Banimento",
["Banishment + Final Warning"] = "Banimento + Aviso final", ["Banishment + Final Warning"] = "Banimento + Aviso final",
["Battle"] = "Batalha", ["Battle"] = "Batalha",
@ -88,9 +87,8 @@ locale = {
["Fishing"] = "Pesca", ["Fishing"] = "Pesca",
["Fist Fighting"] = "Porrada", ["Fist Fighting"] = "Porrada",
["Follow"] = "Seguir", ["Follow"] = "Seguir",
["Foreground pane framerate limit: %s"] = "Limite da taxa de quadros no primeiro plano: %s",
["Frame rate limit"] = "Limite de FPS",
["Fullscreen"] = "Tela cheia", ["Fullscreen"] = "Tela cheia",
["Game framerate limit: %s"] = "Limite da taxa de quadros do jogo: %s",
["General"] = "Geral", ["General"] = "Geral",
["Graphics"] = "Gráficos", ["Graphics"] = "Gráficos",
["Graphics Engine:"] = "Motor Gráfico:", ["Graphics Engine:"] = "Motor Gráfico:",
@ -106,6 +104,7 @@ locale = {
["Hotkeys"] = "Atalhos", ["Hotkeys"] = "Atalhos",
["Ignore capacity"] = "Ignorar capacidade", ["Ignore capacity"] = "Ignorar capacidade",
["Ignore equipped"] = "Ignorar equipado", ["Ignore equipped"] = "Ignorar equipado",
["Interface framerate limit: %s"] = "Limite da taxa de quadros da interface: %s",
["Inventory"] = "Inventário", ["Inventory"] = "Inventário",
["Invite to Party"] = "Convidar para o grupo", ["Invite to Party"] = "Convidar para o grupo",
["Invite to private chat"] = "Convidar para o canal privado", ["Invite to private chat"] = "Convidar para o canal privado",

View File

@ -35,7 +35,7 @@ Panel
Label Label
id: backgroundFrameRateLimitLabel id: backgroundFrameRateLimitLabel
!text: tr('Background pane framerate limit: %s', 'max') !text: tr('Game framerate limit: %s', 'max')
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.top: prev.bottom
@ -59,12 +59,12 @@ Panel
value = 0 value = 0
end end
self:getParent():getChildById('backgroundFrameRateLimitLabel'):setText(tr('Background pane framerate limit: %s', text)) self:getParent():getChildById('backgroundFrameRateLimitLabel'):setText(tr('Game framerate limit: %s', text))
g_app.setBackgroundPaneMaxFps(value) g_app.setBackgroundPaneMaxFps(value)
Label Label
id: foregroundFrameRateLimitLabel id: foregroundFrameRateLimitLabel
!text: tr('Foreground pane framerate limit: %s', '8') !text: tr('Interface framerate limit: %s', '24')
anchors.left: parent.left anchors.left: parent.left
anchors.right: parent.right anchors.right: parent.right
anchors.top: prev.bottom anchors.top: prev.bottom
@ -78,7 +78,7 @@ Panel
margin-top: 3 margin-top: 3
minimum: 1 minimum: 1
maximum: 61 maximum: 61
value: 8 value: 61
step: 1 step: 1
@onValueChange: | @onValueChange: |
local value = self:getValue() local value = self:getValue()
@ -88,6 +88,6 @@ Panel
value = 0 value = 0
end end
self:getParent():getChildById('foregroundFrameRateLimitLabel'):setText(tr('Foreground pane framerate limit: %s', text)) self:getParent():getChildById('foregroundFrameRateLimitLabel'):setText(tr('Interface framerate limit: %s', text))
g_app.setForegroundPaneMaxFps(value) g_app.setForegroundPaneMaxFps(value)

View File

@ -39,6 +39,14 @@ local function setupGraphicsEngines()
g_graphics.selectPainterEngine(2) g_graphics.selectPainterEngine(2)
end end
end end
local foregroundFrameRateScrollBar = graphicsPanel:getChildById('foregroundFrameRateScrollBar')
local foregroundFrameRateLimitLabel = graphicsPanel:getChildById('foregroundFrameRateLimitLabel')
if not g_graphics.canCacheBackbuffer() then
foregroundFrameRateScrollBar:setValue(61)
foregroundFrameRateScrollBar:disable()
foregroundFrameRateLimitLabel:disable()
end
end end
function Options.init() function Options.init()
@ -50,12 +58,12 @@ function Options.init()
end end
end end
Keyboard.bindKeyDown('Ctrl+P', Options.toggle) Keyboard.bindKeyDown('Ctrl+D', Options.toggle)
Keyboard.bindKeyDown('Ctrl+F', function() Options.toggleOption('fullscreen') end) Keyboard.bindKeyDown('Ctrl+F', function() Options.toggleOption('fullscreen') end)
optionsWindow = displayUI('options.otui') optionsWindow = displayUI('options.otui')
optionsWindow:hide() optionsWindow:hide()
optionsButton = TopMenu.addLeftButton('optionsButton', tr('Options') .. ' (Ctrl+P)', 'options.png', Options.toggle) optionsButton = TopMenu.addLeftButton('optionsButton', tr('Options') .. ' (Ctrl+D)', 'options.png', Options.toggle)
optionsTabBar = optionsWindow:getChildById('optionsTabBar') optionsTabBar = optionsWindow:getChildById('optionsTabBar')
optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent')) optionsTabBar:setContentWidget(optionsWindow:getChildById('optionsTabContent'))
@ -69,7 +77,7 @@ function Options.init()
end end
function Options.terminate() function Options.terminate()
Keyboard.unbindKeyDown('Ctrl+P') Keyboard.unbindKeyDown('Ctrl+D')
Keyboard.unbindKeyDown('Ctrl+F') Keyboard.unbindKeyDown('Ctrl+F')
optionsWindow:destroy() optionsWindow:destroy()
optionsWindow = nil optionsWindow = nil

View File

@ -83,6 +83,8 @@ TopPanel
cycleEvent(function() cycleEvent(function()
local frameCounter = rootWidget:recursiveGetChildById('frameCounter') local frameCounter = rootWidget:recursiveGetChildById('frameCounter')
if frameCounter then if frameCounter then
frameCounter:setText('FPS: ' .. g_app.getBackgroundPaneFps()) local text = 'FPS: ' .. g_app.getBackgroundPaneFps()
frameCounter:setText(text)
--print(text)
end end
end, 250) end, 250)

View File

@ -63,10 +63,11 @@ local function updateSlider(self)
slider:setMarginLeft(offset) slider:setMarginLeft(offset)
end end
if self.maximum == self.minimum then local status = (self.maximum ~= self.minimum)
self:disable()
else self:setOn(status)
self:enable() for _i,child in pairs(self:getChildren()) do
child:setEnabled(status)
end end
end end
@ -100,12 +101,10 @@ end
function UIScrollBar:onSetup() function UIScrollBar:onSetup()
self.setupDone = true self.setupDone = true
signalcall(self.onValueChange, self, self.value) signalcall(self.onValueChange, self, self.value)
addEvent(function() Mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:decrement() end)
Mouse.bindAutoPress(self:getChildById('decrementButton'), function() self:decrement() end) Mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:increment() end)
Mouse.bindAutoPress(self:getChildById('incrementButton'), function() self:increment() end) Mouse.bindPressMove(self:getChildById('sliderButton'), function(mousePos, mouseMoved) parseSliderPos(self, mousePos) end)
Mouse.bindPressMove(self:getChildById('sliderButton'), function(mousePos, mouseMoved) parseSliderPos(self, mousePos) end) updateSlider(self)
updateSlider(self)
end)
end end
function UIScrollBar:onStyleApply(styleName, styleNode) function UIScrollBar:onStyleApply(styleName, styleNode)

View File

@ -41,6 +41,7 @@ end
function UIItem:onHoverChange(hovered) function UIItem:onHoverChange(hovered)
UIWidget.onHoverChange(self, hovered) UIWidget.onHoverChange(self, hovered)
if self:isVirtual() then return end if self:isVirtual() then return end
local draggingWidget = g_ui.getDraggingWidget() local draggingWidget = g_ui.getDraggingWidget()

View File

@ -6,10 +6,8 @@ function UIMiniWindow.create()
end end
function UIMiniWindow:onSetup() function UIMiniWindow:onSetup()
addEvent(function() self:getChildById('closeButton').onClick = function() signalcall(self.onClose, self) end
self:getChildById('closeButton').onClick = function() signalcall(self.onClose, self) end self:getChildById('minimizeButton').onClick = function() signalcall(self.onMinimize, self) end
self:getChildById('minimizeButton').onClick = function() signalcall(self.onMinimize, self) end
end)
end end
function UIMiniWindow:onDragEnter(mousePos) function UIMiniWindow:onDragEnter(mousePos)

View File

@ -44,6 +44,7 @@ local SayModes = {
local MAX_HISTORY = 1000 local MAX_HISTORY = 1000
local MAX_LINES = 100 local MAX_LINES = 100
local HELP_CHANNEL = 9
local consolePanel local consolePanel
local consoleContentPanel local consoleContentPanel
@ -221,6 +222,7 @@ function Console.init()
-- tibia like hotkeys -- tibia like hotkeys
Keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels) Keyboard.bindKeyDown('Ctrl+O', g_game.requestChannels)
Keyboard.bindKeyDown('Ctrl+E', Console.removeCurrentTab) Keyboard.bindKeyDown('Ctrl+E', Console.removeCurrentTab)
Keyboard.bindKeyDown('Ctrl+H', Console.openHelp)
end end
function Console.terminate() function Console.terminate()
@ -242,6 +244,7 @@ function Console.terminate()
Keyboard.unbindKeyDown('Ctrl+O') Keyboard.unbindKeyDown('Ctrl+O')
Keyboard.unbindKeyDown('Ctrl+E') Keyboard.unbindKeyDown('Ctrl+E')
Keyboard.unbindKeyDown('Ctrl+H')
if channelsWindow then if channelsWindow then
channelsWindow:destroy() channelsWindow:destroy()
@ -287,6 +290,10 @@ function Console.setTextEditText(text)
consoleTextEdit:setText(text) consoleTextEdit:setText(text)
end end
function Console.openHelp()
g_game.joinChannel(HELP_CHANNEL)
end
function Console.addTab(name, focus) function Console.addTab(name, focus)
local tab = consoleTabBar:addTab(name) local tab = consoleTabBar:addTab(name)
if focus then if focus then

View File

@ -12,14 +12,17 @@ function VipList.init()
onVipStateChange = VipList.onVipStateChange }) onVipStateChange = VipList.onVipStateChange })
Keyboard.bindKeyDown('Ctrl+P', VipList.toggle)
vipWindow = displayUI('viplist.otui', GameInterface.getLeftPanel()) vipWindow = displayUI('viplist.otui', GameInterface.getLeftPanel())
vipButton = TopMenu.addGameToggleButton('vipListButton', tr('VIP list'), 'viplist.png', VipList.toggle) vipButton = TopMenu.addGameToggleButton('vipListButton', tr('VIP list') .. ' (Ctrl+P)', 'viplist.png', VipList.toggle)
vipButton:setOn(true) vipButton:setOn(true)
VipList.refresh() VipList.refresh()
end end
function VipList.terminate() function VipList.terminate()
Keyboard.unbindKeyDown('Ctrl+P')
disconnect(g_game, { onGameEnd = VipList.clear, disconnect(g_game, { onGameEnd = VipList.clear,
onAddVip = VipList.onAddVip, onAddVip = VipList.onAddVip,
onVipStateChange = VipList.onVipStateChange }) onVipStateChange = VipList.onVipStateChange })

View File

@ -167,6 +167,7 @@ void Application::run()
if(!m_initialized) if(!m_initialized)
return; return;
bool cacheForeground = true;
m_stopping = false; m_stopping = false;
m_running = true; m_running = true;
@ -189,6 +190,15 @@ void Application::run()
bool redraw = false; bool redraw = false;
bool updateForeground = false; bool updateForeground = false;
bool canCacheForeground = g_graphics.canCacheBackbuffer() && m_foregroundFrameCounter.getMaxFps() != 0;
if(cacheForeground != canCacheForeground) {
cacheForeground = canCacheForeground;
if(cacheForeground)
glColorMask(1,1,1,1);
else
glColorMask(1,1,1,0);
}
if(m_backgroundFrameCounter.shouldProcessNextFrame()) { if(m_backgroundFrameCounter.shouldProcessNextFrame()) {
redraw = true; redraw = true;
@ -201,29 +211,35 @@ void Application::run()
if(redraw) { if(redraw) {
g_graphics.beginRender(); g_graphics.beginRender();
Rect viewportRect(0, 0, g_graphics.getViewportSize()); if(cacheForeground) {
Rect viewportRect(0, 0, g_graphics.getViewportSize());
// draw the foreground into a texture // draw the foreground into a texture
if(updateForeground) { if(updateForeground) {
m_foregroundFrameCounter.processNextFrame();
// draw foreground
g_painter->clear(Color::black);
g_ui.render(Fw::ForegroundPane);
// copy the foreground to a texture
m_foreground->copyFromScreen(viewportRect);
}
// draw background (animated stuff)
m_backgroundFrameCounter.processNextFrame();
g_ui.render(Fw::BackgroundPane);
// draw the foreground (steady stuff)
g_painter->setColor(Color::white);
g_painter->setOpacity(1.0);
g_painter->drawTexturedRect(viewportRect, m_foreground, viewportRect);
} else {
m_foregroundFrameCounter.processNextFrame(); m_foregroundFrameCounter.processNextFrame();
m_backgroundFrameCounter.processNextFrame();
// draw foreground g_ui.render(Fw::BothPanes);
g_painter->clear(Color::black);
g_ui.render(true);
// copy the foreground to a texture
m_foreground->copyFromScreen(viewportRect);
} }
// draw background (animated stuff)
m_backgroundFrameCounter.processNextFrame();
g_ui.render(false);
// draw the foreground (steady stuff)
g_painter->setColor(Color::white);
g_painter->setOpacity(1.0);
g_painter->drawTexturedRect(viewportRect, m_foreground, viewportRect);
g_graphics.endRender(); g_graphics.endRender();
// update screen pixels // update screen pixels
@ -237,9 +253,8 @@ void Application::run()
m_foregroundFrameCounter.update(); m_foregroundFrameCounter.update();
int sleepMicros = std::min(m_backgroundFrameCounter.getMaximumSleepMicros(), m_foregroundFrameCounter.getMaximumSleepMicros()); int sleepMicros = std::min(m_backgroundFrameCounter.getMaximumSleepMicros(), m_foregroundFrameCounter.getMaximumSleepMicros());
if(sleepMicros >= AdaptativeFrameCounter::MINIMUM_MICROS_SLEEP) { if(sleepMicros >= AdaptativeFrameCounter::MINIMUM_MICROS_SLEEP)
stdext::microsleep(AdaptativeFrameCounter::MINIMUM_MICROS_SLEEP); stdext::microsleep(AdaptativeFrameCounter::MINIMUM_MICROS_SLEEP);
}
} else { } else {
// sleeps until next poll to avoid massive cpu usage // sleeps until next poll to avoid massive cpu usage
@ -285,8 +300,10 @@ void Application::resize(const Size& size)
g_ui.resize(size); g_ui.resize(size);
m_onInputEvent = false; m_onInputEvent = false;
m_foreground = TexturePtr(new Texture(size.width(), size.height())); if(g_graphics.canCacheBackbuffer()) {
m_foreground->setUpsideDown(true); m_foreground = TexturePtr(new Texture(size));
m_foreground->setUpsideDown(true);
}
m_mustRepaint = true; m_mustRepaint = true;
} }

View File

@ -262,6 +262,12 @@ namespace Fw
DraggingState = 2048, DraggingState = 2048,
LastWidgetState = 4096 LastWidgetState = 4096
}; };
enum DrawPane {
ForegroundPane = 1,
BackgroundPane = 2,
BothPanes = 3
};
} }
#endif #endif

View File

@ -24,7 +24,7 @@
#include "graphics.h" #include "graphics.h"
#include <framework/core/eventdispatcher.h> #include <framework/core/eventdispatcher.h>
/*
AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) : AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFrames, uchar *framesPixels, int *framesDelay) :
Texture(), Texture(),
m_numFrames(numFrames) m_numFrames(numFrames)
@ -48,7 +48,7 @@ AnimatedTexture::AnimatedTexture(int width, int height, int channels, int numFra
AnimatedTexture::~AnimatedTexture() AnimatedTexture::~AnimatedTexture()
{ {
glDeleteTextures(m_numFrames, &m_framesTextureId[0]); glDeleteTextures(m_numFrames, &m_framesTextureId[0]);
m_textureId = 0; m_id = 0;
} }
void AnimatedTexture::enableBilinearFilter() void AnimatedTexture::enableBilinearFilter()
@ -65,7 +65,7 @@ void AnimatedTexture::processAnimation()
m_currentFrame++; m_currentFrame++;
if(m_currentFrame >= m_numFrames) if(m_currentFrame >= m_numFrames)
m_currentFrame = 0; m_currentFrame = 0;
m_textureId = m_framesTextureId[m_currentFrame]; m_id = m_framesTextureId[m_currentFrame];
AnimatedTexturePtr self = asAnimatedTexture(); AnimatedTexturePtr self = asAnimatedTexture();
@ -73,3 +73,4 @@ void AnimatedTexture::processAnimation()
if(self.use_count() > 1) if(self.use_count() > 1)
g_eventDispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, self), m_framesDelay[m_currentFrame]); g_eventDispatcher.scheduleEvent(std::bind(&AnimatedTexture::processAnimation, self), m_framesDelay[m_currentFrame]);
} }
*/

View File

@ -24,7 +24,7 @@
#define ANIMATEDTEXTURE_H #define ANIMATEDTEXTURE_H
#include "texture.h" #include "texture.h"
/*
class AnimatedTexture : public Texture class AnimatedTexture : public Texture
{ {
public: public:
@ -43,5 +43,5 @@ private:
int m_currentFrame; int m_currentFrame;
ticks_t m_lastAnimCheckTicks; ticks_t m_lastAnimCheckTicks;
}; };
*/
#endif #endif

View File

@ -63,7 +63,7 @@ void FrameBuffer::resize(const Size& size)
if(m_texture && m_texture->getSize() == size) if(m_texture && m_texture->getSize() == size)
return; return;
m_texture = TexturePtr(new Texture(size.width(), size.height(), 4)); m_texture = TexturePtr(new Texture(size));
m_texture->setSmooth(true); m_texture->setSmooth(true);
m_texture->setUpsideDown(true); m_texture->setUpsideDown(true);
@ -76,8 +76,10 @@ void FrameBuffer::resize(const Size& size)
g_logger.fatal("Unable to setup framebuffer object"); g_logger.fatal("Unable to setup framebuffer object");
internalRelease(); internalRelease();
} else { } else {
m_screenBackup = TexturePtr(new Texture(size.width(), size.height())); if(m_backuping) {
m_screenBackup->setUpsideDown(true); m_screenBackup = TexturePtr(new Texture(size));
m_screenBackup->setUpsideDown(true);
}
} }
} }
@ -126,7 +128,7 @@ void FrameBuffer::internalBind()
glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
m_prevBoundFbo = boundFbo; m_prevBoundFbo = boundFbo;
boundFbo = m_fbo; boundFbo = m_fbo;
} else { } else if(m_backuping) {
// backup screen color buffer into a texture // backup screen color buffer into a texture
m_screenBackup->copyFromScreen(Rect(0, 0, getSize())); m_screenBackup->copyFromScreen(Rect(0, 0, getSize()));
} }
@ -145,10 +147,12 @@ void FrameBuffer::internalRelease()
m_texture->copyFromScreen(screenRect); m_texture->copyFromScreen(screenRect);
// restore screen original content // restore screen original content
Painter::CompositionMode oldComposition = g_painter->getCompositionMode(); if(m_backuping) {
g_painter->setCompositionMode(Painter::CompositionMode_Replace); Painter::CompositionMode oldComposition = g_painter->getCompositionMode();
g_painter->drawTexturedRect(screenRect, m_screenBackup, screenRect); g_painter->setCompositionMode(Painter::CompositionMode_Replace);
g_painter->setCompositionMode(oldComposition); g_painter->drawTexturedRect(screenRect, m_screenBackup, screenRect);
g_painter->setCompositionMode(oldComposition);
}
} }
} }

View File

@ -40,8 +40,11 @@ public:
void draw(const Rect& dest); void draw(const Rect& dest);
void draw(const Rect& dest, const Rect& src); void draw(const Rect& dest, const Rect& src);
void setBackuping(bool enabled) { m_backuping = enabled; }
TexturePtr getTexture() { return m_texture; } TexturePtr getTexture() { return m_texture; }
Size getSize(); Size getSize();
bool isBackuping() { return m_backuping; }
private: private:
void internalCreate(); void internalCreate();
@ -53,6 +56,7 @@ private:
Size m_oldViewportSize; Size m_oldViewportSize;
uint m_fbo; uint m_fbo;
uint m_prevBoundFbo; uint m_prevBoundFbo;
Boolean<true> m_backuping;
static uint boundFbo; static uint boundFbo;
}; };

View File

@ -92,12 +92,6 @@ void Graphics::init()
if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize) if(m_maxTextureSize == -1 || m_maxTextureSize > maxTextureSize)
m_maxTextureSize = maxTextureSize; m_maxTextureSize = maxTextureSize;
// check if we have alpha channel in the color buffer, because we need alpha channel for glCopyTexSubImage2D
GLint alphaBits = 0;
glGetIntegerv(GL_ALPHA_BITS, &alphaBits);
if(alphaBits <= 0)
g_logger.fatal("OpenGL visual doesn't have an alpha buffer");
selectPainterEngine(m_prefferedPainterEngine); selectPainterEngine(m_prefferedPainterEngine);
m_emptyTexture = TexturePtr(new Texture); m_emptyTexture = TexturePtr(new Texture);
} }
@ -143,6 +137,8 @@ bool Graphics::parseOption(const std::string& option)
m_useNonPowerOfTwoTextures = false; m_useNonPowerOfTwoTextures = false;
else if(option == "-no-clamp-to-edge") else if(option == "-no-clamp-to-edge")
m_useClampToEdge = false; m_useClampToEdge = false;
else if(option == "-no-backbuffer-cache")
m_cacheBackbuffer = false;
else if(option == "-opengl1") else if(option == "-opengl1")
m_prefferedPainterEngine = Painter_OpenGL1; m_prefferedPainterEngine = Painter_OpenGL1;
else if(option == "-opengl2") else if(option == "-opengl2")
@ -368,3 +364,16 @@ bool Graphics::canUseBlendFuncSeparate()
return true; return true;
#endif #endif
} }
bool Graphics::canCacheBackbuffer()
{
#if OPENGL_ES==2
return m_cacheBackbuffer;
#elif OPENGL_ES==1
return false;
#else
if(!GLEW_VERSION_1_4)
return false;
return m_cacheBackbuffer;
#endif
}

View File

@ -70,6 +70,7 @@ public:
bool canUseHardwareMipmaps(); bool canUseHardwareMipmaps();
bool canUseClampToEdge(); bool canUseClampToEdge();
bool canUseBlendFuncSeparate(); bool canUseBlendFuncSeparate();
bool canCacheBackbuffer();
private: private:
Size m_viewportSize; Size m_viewportSize;
@ -84,6 +85,7 @@ private:
Boolean<true> m_useMipmaps; Boolean<true> m_useMipmaps;
Boolean<true> m_useHardwareMipmaps; Boolean<true> m_useHardwareMipmaps;
Boolean<true> m_useClampToEdge; Boolean<true> m_useClampToEdge;
Boolean<true> m_cacheBackbuffer;
PainterEngine m_prefferedPainterEngine; PainterEngine m_prefferedPainterEngine;
PainterEngine m_selectedPainterEngine; PainterEngine m_selectedPainterEngine;
}; };

View File

@ -30,7 +30,7 @@ Image::Image(const Size& size, int bpp, uint8 *pixels)
{ {
m_size = size; m_size = size;
m_bpp = bpp; m_bpp = bpp;
m_pixels.resize(size.area() * bpp); m_pixels.resize(size.area() * bpp, 0);
if(pixels) if(pixels)
memcpy(&m_pixels[0], pixels, m_pixels.size()); memcpy(&m_pixels[0], pixels, m_pixels.size());
} }
@ -84,8 +84,10 @@ void Image::overwriteMask(const Color& maskedColor, const Color& insideColor, co
} }
} }
void Image::append(const Point& dest, const ImagePtr& other) void Image::blit(const Point& dest, const ImagePtr& other)
{ {
assert(m_bpp == 4);
if(!other) if(!other)
return; return;
@ -103,3 +105,109 @@ void Image::append(const Point& dest, const ImagePtr& other)
} }
} }
} }
void Image::paste(const ImagePtr& other)
{
assert(m_bpp == 4);
if(!other)
return;
uint8* otherPixels = other->getPixelData();
for(int p = 0; p < other->getPixelCount(); ++p) {
int x = p % other->getWidth();
int y = p / other->getWidth();
int pos = (y * m_size.width() + x) * 4;
m_pixels[pos+0] = otherPixels[p*4+0];
m_pixels[pos+1] = otherPixels[p*4+1];
m_pixels[pos+2] = otherPixels[p*4+2];
m_pixels[pos+3] = otherPixels[p*4+3];
}
}
bool Image::nextMipmap()
{
assert(m_bpp == 4);
assert(stdext::is_power_of_two(m_size.width()) && stdext::is_power_of_two(m_size.height()));
if(m_size.width() == 1 || m_size.height() == 1)
return false;
Size size = m_size / 2;
std::vector<uint8> pixels(size.area()*4, 0xFF);
m_pixels = pixels;
m_size = size;
return true;
}
/*
*
void Texture::generateSoftwareMipmaps(std::vector<uint8> inPixels)
{
bind();
assert(stdext::is_power_of_two(m_glSize.width()) && stdext::is_power_of_two(m_glSize.height()));
Size inSize = m_glSize;
Size outSize = inSize / 2;
std::vector<uint8> outPixels;
int mipmap = 1;
while(true) {
outPixels.resize(outSize.area()*4, 0);
// this is a simple bilinear filtering algorithm, it combines every 4 pixels in one pixel
for(int x=0;x<outSize.width();++x) {
for(int y=0;y<outSize.height();++y) {
uint8 *inPixel[4];
inPixel[0] = &inPixels[((y*2)*inSize.width() + (x*2))*4];
inPixel[1] = &inPixels[((y*2)*inSize.width() + (x*2)+1)*4];
inPixel[2] = &inPixels[((y*2+1)*inSize.width() + (x*2))*4];
inPixel[3] = &inPixels[((y*2+1)*inSize.width() + (x*2)+1)*4];
uint8 *outPixel = &outPixels[(y*outSize.width() + x)*4];
int pixelsSum[4];
for(int i=0;i<4;++i)
pixelsSum[i] = 0;
int usedPixels = 0;
for(int j=0;j<4;++j) {
// ignore colors of complete alpha pixels
if(inPixel[j][3] < 16)
continue;
for(int i=0;i<4;++i)
pixelsSum[i] += inPixel[j][i];
usedPixels++;
}
// try to guess the alpha pixel more accurately
for(int i=0;i<4;++i) {
if(usedPixels > 0)
outPixel[i] = pixelsSum[i] / usedPixels;
else
outPixel[i] = 0;
}
outPixel[3] = pixelsSum[3]/4;
}
}
glTexImage2D(GL_TEXTURE_2D, mipmap++, GL_RGBA, outSize.width(), outSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &outPixels[0]);
if(inSize.width() == 1 || inSize.height() == 1)
break;
inPixels = std::move(outPixels);
inSize /= 2;
outSize /= 2;
}
if(!m_hasMipmaps) {
m_hasMipmaps = true;
setupFilters();
}
}
*/

View File

@ -35,7 +35,9 @@ public:
static ImagePtr loadPNG(const std::string& file); static ImagePtr loadPNG(const std::string& file);
void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha); void overwriteMask(const Color& maskedColor, const Color& insideColor = Color::white, const Color& outsideColor = Color::alpha);
void append(const Point& dest, const ImagePtr &other); void blit(const Point& dest, const ImagePtr& other);
void paste(const ImagePtr& other);
bool nextMipmap();
std::vector<uint8>& getPixels() { return m_pixels; } std::vector<uint8>& getPixels() { return m_pixels; }
uint8* getPixelData() { return &m_pixels[0]; } uint8* getPixelData() { return &m_pixels[0]; }

View File

@ -27,104 +27,68 @@
Texture::Texture() Texture::Texture()
{ {
m_textureId = 0; m_id = 0;
} }
Texture::Texture(const ImagePtr& image) Texture::Texture(const Size& size)
{ {
internalLoadGLTexture(image->getPixelData(), image->getBpp(), image->getWidth(), image->getHeight()); m_id = 0;
if(!setupSize(size))
return;
createTexture();
bind();
setupPixels(0, m_glSize, nullptr, 4);
setupWrap();
setupFilters();
} }
Texture::Texture(int width, int height, int channels, uchar *pixels) Texture::Texture(const ImagePtr& image, bool buildMipmaps)
{ {
// generate opengl texture m_id = 0;
internalLoadGLTexture(pixels, channels, width, height);
if(!setupSize(image->getSize(), buildMipmaps))
return;
createTexture();
ImagePtr glImage = image;
if(m_size != m_glSize) {
glImage = ImagePtr(new Image(m_glSize, image->getBpp()));
glImage->paste(image);
} else
glImage = image;
bind();
/*
if(buildMipmaps) {
int level = 0;
do {
setupPixels(level++, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
} while(glImage->nextMipmap());
m_hasMipmaps = true;
} else
*/
setupPixels(0, glImage->getSize(), glImage->getPixelData(), glImage->getBpp());
setupWrap();
setupFilters();
} }
Texture::~Texture() Texture::~Texture()
{ {
// free texture from gl memory // free texture from gl memory
if(m_textureId > 0) if(m_id > 0)
glDeleteTextures(1, &m_textureId); glDeleteTextures(1, &m_id);
} }
uint Texture::internalLoadGLTexture(uchar *pixels, int channels, int width, int height) void Texture::bind()
{ {
m_size.resize(width, height); // must reset painter texture state
g_painter->setTexture(this);
// convert texture pixel data to power of two size, only required for OpenGL 1.5 or older glBindTexture(GL_TEXTURE_2D, m_id);
std::vector<uint8> tmp;
if(!g_graphics.canUseNonPowerOfTwoTextures()) {
int glWidth = 1;
while(glWidth < width)
glWidth = glWidth << 1;
int glHeight = 1;
while(glHeight < height)
glHeight = glHeight << 1;
if(m_size != m_glSize && pixels) {
tmp.resize(glHeight*glWidth*channels, 0);
for(int y=0; y<height; ++y)
for(int x=0; x<width; ++x)
for(int i=0; i<channels; ++i)
tmp[y*glWidth*channels+x*channels+i] = pixels[y*width*channels+x*channels+i];
pixels = &tmp[0];
}
m_glSize.resize(glWidth, glHeight);
} else
m_glSize = m_size;
setupTranformMatrix();
// checks texture max size
if(std::max(m_glSize.width(), m_glSize.height()) > g_graphics.getMaxTextureSize()) {
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
"the maximum size allowed by the graphics card is %dx%d,"
"to prevent crashes the texture will be displayed as a blank texture",
width, height, g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
//TODO: make a workaround, could be bilinear scaling the texture
return 0;
}
// generate gl texture
GLuint id;
glGenTextures(1, &id);
assert(id != 0);
m_textureId = id;
bind();
// detect pixels GL format
GLenum format = 0;
switch(channels) {
case 4:
format = GL_RGBA;
break;
case 3:
format = GL_RGB;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 1:
format = GL_LUMINANCE;
break;
}
// load pixels into gl memory
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_glSize.width(), m_glSize.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
GLint texParam = GL_REPEAT;
if(g_graphics.canUseClampToEdge())
texParam = GL_CLAMP_TO_EDGE; // disable texture borders by default
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
setupFilters();
return id;
} }
void Texture::copyFromScreen(const Rect& screenRect) void Texture::copyFromScreen(const Rect& screenRect)
@ -133,25 +97,7 @@ void Texture::copyFromScreen(const Rect& screenRect)
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height()); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, screenRect.x(), screenRect.y(), screenRect.width(), screenRect.height());
} }
void Texture::bind() bool Texture::buildHardwareMipmaps()
{
// must reset painter texture state
g_painter->setTexture(this);
glBindTexture(GL_TEXTURE_2D, m_textureId);
}
void Texture::generateMipmaps()
{
if(!generateHardwareMipmaps()) {
// fallback to software mipmaps generation, this can be slow
//FIXME: disabled because mipmaps size needs to be in base of 2,
// and the current algorithmn does not support that
//generateSoftwareMipmaps(getPixels());
g_logger.traceError("non power of 2.");
}
}
bool Texture::generateHardwareMipmaps()
{ {
if(!g_graphics.canUseHardwareMipmaps()) if(!g_graphics.canUseHardwareMipmaps())
return false; return false;
@ -188,69 +134,43 @@ void Texture::setUpsideDown(bool upsideDown)
setupTranformMatrix(); setupTranformMatrix();
} }
void Texture::generateSoftwareMipmaps(std::vector<uint8> inPixels) void Texture::createTexture()
{ {
bind(); glGenTextures(1, &m_id);
assert(m_id != 0);
}
if(!m_hasMipmaps) { bool Texture::setupSize(const Size& size, bool forcePowerOfTwo)
m_hasMipmaps = true; {
setupFilters(); Size glSize;
if(!g_graphics.canUseNonPowerOfTwoTextures() || forcePowerOfTwo)
glSize.resize(stdext::to_power_of_two(size.width()), stdext::to_power_of_two(size.height()));
else
glSize = size;
// checks texture max size
if(std::max(glSize.width(), glSize.height()) > g_graphics.getMaxTextureSize()) {
g_logger.error(stdext::format("loading texture with size %dx%d failed, "
"the maximum size allowed by the graphics card is %dx%d,"
"to prevent crashes the texture will be displayed as a blank texture",
size.width(), size.height(), g_graphics.getMaxTextureSize(), g_graphics.getMaxTextureSize()));
return false;
} }
Size inSize = getSize(); m_size = size;
Size outSize = inSize / 2; m_glSize = glSize;
std::vector<uint8> outPixels; setupTranformMatrix();
return true;
}
int mipmap = 1; void Texture::setupWrap()
while(true) { {
outPixels.resize(outSize.area()*4); GLint texParam = GL_REPEAT;
if(g_graphics.canUseClampToEdge())
texParam = GL_CLAMP_TO_EDGE; // disable texture borders by default
// this is a simple bilinear filtering algorithm, it combines every 4 pixels in one pixel glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, texParam);
for(int x=0;x<outSize.width();++x) { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, texParam);
for(int y=0;y<outSize.height();++y) {
uint8 *inPixel[4];
inPixel[0] = &inPixels[((y*2)*inSize.width() + (x*2))*4];
inPixel[1] = &inPixels[((y*2)*inSize.width() + (x*2)+1)*4];
inPixel[2] = &inPixels[((y*2+1)*inSize.width() + (x*2))*4];
inPixel[3] = &inPixels[((y*2+1)*inSize.width() + (x*2)+1)*4];
uint8 *outPixel = &outPixels[(y*outSize.width() + x)*4];
int pixelsSum[4];
for(int i=0;i<4;++i)
pixelsSum[i] = 0;
int usedPixels = 0;
for(int j=0;j<4;++j) {
// ignore colors of complete alpha pixels
if(inPixel[j][3] < 16)
continue;
for(int i=0;i<4;++i)
pixelsSum[i] += inPixel[j][i];
usedPixels++;
}
// try to guess the alpha pixel more accurately
for(int i=0;i<4;++i) {
if(usedPixels > 0)
outPixel[i] = pixelsSum[i] / usedPixels;
else
outPixel[i] = 0;
}
outPixel[3] = pixelsSum[3]/4;
}
}
glTexImage2D(GL_TEXTURE_2D, mipmap++, GL_RGBA, outSize.width(), outSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, &outPixels[0]);
if(inSize.width() == 1 || inSize.height() == 1)
break;
inPixels = std::move(outPixels);
inSize /= 2;
outSize /= 2;
}
} }
void Texture::setupFilters() void Texture::setupFilters()
@ -280,3 +200,24 @@ void Texture::setupTranformMatrix()
0.0f, 0.0f, 1.0f }; 0.0f, 0.0f, 1.0f };
} }
} }
void Texture::setupPixels(int level, const Size& size, uchar* pixels, int channels)
{
GLenum format = 0;
switch(channels) {
case 4:
format = GL_RGBA;
break;
case 3:
format = GL_RGB;
break;
case 2:
format = GL_LUMINANCE_ALPHA;
break;
case 1:
format = GL_LUMINANCE;
break;
}
glTexImage2D(GL_TEXTURE_2D, level, GL_RGBA, size.width(), size.height(), 0, format, GL_UNSIGNED_BYTE, pixels);
}

View File

@ -29,41 +29,35 @@ class Texture : public std::enable_shared_from_this<Texture>
{ {
public: public:
Texture(); Texture();
Texture(const ImagePtr& image); Texture(const Size& size);
Texture(int width, int height, int channels = 4, uchar* pixels = NULL); Texture(const ImagePtr& image, bool buildMipmaps = false);
virtual ~Texture(); virtual ~Texture();
void copyFromScreen(const Rect& screenRect);
void bind(); void bind();
void copyFromScreen(const Rect& screenRect);
bool buildHardwareMipmaps();
/// Tries to generate mipmaps via hardware, otherwise fallback to software implementation
void generateMipmaps();
/// Generate mipmaps via hardware if supported
bool generateHardwareMipmaps();
/// Generate mipmaps via software, which has a special algorithm for combining alpha pixels
void generateSoftwareMipmaps(std::vector<uint8> inPixels);
/// Activate texture anti-aliasing giving a better look when they are resized
void setSmooth(bool smooth); void setSmooth(bool smooth);
void setUpsideDown(bool upsideDown); void setUpsideDown(bool upsideDown);
GLuint getId() { return m_textureId; } GLuint getId() { return m_id; }
int getWidth() { return m_size.width(); } int getWidth() { return m_size.width(); }
int getHeight() { return m_size.height(); } int getHeight() { return m_size.height(); }
const Size& getSize() { return m_size; } const Size& getSize() { return m_size; }
const Size& getGlSize() { return m_glSize; }
const Matrix3& getTransformMatrix() { return m_transformMatrix; } const Matrix3& getTransformMatrix() { return m_transformMatrix; }
bool isEmpty() { return m_id == 0; }
bool isEmpty() { return m_textureId == 0; }
bool hasMipmaps() { return m_hasMipmaps; } bool hasMipmaps() { return m_hasMipmaps; }
protected: protected:
void createTexture();
bool setupSize(const Size& size, bool forcePowerOfTwo = false);
void setupWrap();
void setupFilters(); void setupFilters();
void setupTranformMatrix(); void setupTranformMatrix();
GLuint internalLoadGLTexture(uchar* pixels, int channels, int w, int h); void setupPixels(int level, const Size& size, uchar *pixels, int channels = 4);
GLuint m_textureId; GLuint m_id;
Size m_size; Size m_size;
Size m_glSize; Size m_glSize;
Matrix3 m_transformMatrix; Matrix3 m_transformMatrix;

View File

@ -23,6 +23,7 @@
#include "texturemanager.h" #include "texturemanager.h"
#include "animatedtexture.h" #include "animatedtexture.h"
#include "graphics.h" #include "graphics.h"
#include "image.h"
#include <framework/core/resourcemanager.h> #include <framework/core/resourcemanager.h>
#include <framework/thirdparty/apngloader.h> #include <framework/thirdparty/apngloader.h>
@ -75,10 +76,13 @@ TexturePtr TextureManager::loadPNG(std::stringstream& file)
apng_data apng; apng_data apng;
if(load_apng(file, &apng) == 0) { if(load_apng(file, &apng) == 0) {
if(apng.num_frames > 1) { // animated texture if(apng.num_frames > 1) { // animated texture
uchar *framesdata = apng.pdata + (apng.first_frame * apng.width * apng.height * apng.bpp); //uchar *framesdata = apng.pdata + (apng.first_frame * apng.width * apng.height * apng.bpp);
texture = TexturePtr(new AnimatedTexture(apng.width, apng.height, apng.bpp, apng.num_frames, framesdata, (int*)apng.frames_delay)); //texture = TexturePtr(new AnimatedTexture(apng.width, apng.height, apng.bpp, apng.num_frames, framesdata, (int*)apng.frames_delay));
} else g_logger.error("animated textures is disabled for a while");
texture = TexturePtr(new Texture(apng.width, apng.height, apng.bpp, apng.pdata)); } else {
ImagePtr image = ImagePtr(new Image(Size(apng.width, apng.height), apng.bpp, apng.pdata));
texture = TexturePtr(new Texture(image));
}
free_apng(&apng); free_apng(&apng);
} }

View File

@ -554,6 +554,7 @@ void Application::registerLuaFunctions()
g_lua.registerStaticClass("g_graphics"); g_lua.registerStaticClass("g_graphics");
g_lua.bindClassStaticFunction("g_graphics", "isPainterEngineAvailable", std::bind(&Graphics::isPainterEngineAvailable, &g_graphics, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_graphics", "isPainterEngineAvailable", std::bind(&Graphics::isPainterEngineAvailable, &g_graphics, std::placeholders::_1));
g_lua.bindClassStaticFunction("g_graphics", "selectPainterEngine", std::bind(&Graphics::selectPainterEngine, &g_graphics, std::placeholders::_1)); g_lua.bindClassStaticFunction("g_graphics", "selectPainterEngine", std::bind(&Graphics::selectPainterEngine, &g_graphics, std::placeholders::_1));
g_lua.bindClassStaticFunction("g_graphics", "canCacheBackbuffer", std::bind(&Graphics::canCacheBackbuffer, &g_graphics));
g_lua.bindClassStaticFunction("g_graphics", "getPainterEngine", std::bind(&Graphics::getPainterEngine, &g_graphics)); g_lua.bindClassStaticFunction("g_graphics", "getPainterEngine", std::bind(&Graphics::getPainterEngine, &g_graphics));
g_lua.bindClassStaticFunction("g_graphics", "getViewportSize", std::bind(&Graphics::getViewportSize, &g_graphics)); g_lua.bindClassStaticFunction("g_graphics", "getViewportSize", std::bind(&Graphics::getViewportSize, &g_graphics));
g_lua.bindClassStaticFunction("g_graphics", "getVendor", std::bind(&Graphics::getVendor, &g_graphics)); g_lua.bindClassStaticFunction("g_graphics", "getVendor", std::bind(&Graphics::getVendor, &g_graphics));

View File

@ -319,7 +319,6 @@ void WIN32Window::internalChooseGLVisual()
if(!pixelFormat) if(!pixelFormat)
g_logger.fatal("Could not find a suitable pixel format"); g_logger.fatal("Could not find a suitable pixel format");
pfd.cStencilBits = 8;
if(!SetPixelFormat(m_deviceContext, pixelFormat, &pfd)) if(!SetPixelFormat(m_deviceContext, pixelFormat, &pfd))
g_logger.fatal("Could not set the pixel format"); g_logger.fatal("Could not set the pixel format");
} }

View File

@ -370,10 +370,10 @@ void X11Window::internalChooseGLVisual()
#else #else
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
#endif #endif
EGL_RED_SIZE, 4, EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 4, EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 4, EGL_BLUE_SIZE, 5,
EGL_ALPHA_SIZE, 4, EGL_ALPHA_SIZE, 0,
EGL_NONE EGL_NONE
}; };

View File

@ -52,9 +52,9 @@ void UIManager::terminate()
m_pressedWidget = nullptr; m_pressedWidget = nullptr;
} }
void UIManager::render(bool foregroundPane) void UIManager::render(Fw::DrawPane drawPane)
{ {
m_rootWidget->draw(m_rootWidget->getRect(), foregroundPane); m_rootWidget->draw(m_rootWidget->getRect(), drawPane);
} }
void UIManager::resize(const Size& size) void UIManager::resize(const Size& size)

View File

@ -33,7 +33,7 @@ public:
void init(); void init();
void terminate(); void terminate();
void render(bool foregroundPane); void render(Fw::DrawPane drawPane);
void resize(const Size& size); void resize(const Size& size);
void inputEvent(const InputEvent& event); void inputEvent(const InputEvent& event);

View File

@ -41,9 +41,9 @@ UITextEdit::UITextEdit()
blinkCursor(); blinkCursor();
} }
void UITextEdit::drawSelf(bool foregroundPane) void UITextEdit::drawSelf(Fw::DrawPane drawPane)
{ {
if(!foregroundPane) if((drawPane & Fw::ForegroundPane) == 0)
return; return;
drawBackground(m_rect); drawBackground(m_rect);

View File

@ -30,7 +30,7 @@ class UITextEdit : public UIWidget
public: public:
UITextEdit(); UITextEdit();
void drawSelf(bool foregroundPane); void drawSelf(Fw::DrawPane drawPane);
private: private:
void update(); void update();

View File

@ -52,27 +52,27 @@ UIWidget::~UIWidget()
#endif #endif
} }
void UIWidget::draw(const Rect& visibleRect, bool foregroundPane) void UIWidget::draw(const Rect& visibleRect, Fw::DrawPane drawPane)
{ {
if(m_clipping) if(m_clipping)
g_painter->setClipRect(visibleRect); g_painter->setClipRect(visibleRect);
drawSelf(foregroundPane); drawSelf(drawPane);
if(m_children.size() > 0) { if(m_children.size() > 0) {
if(m_clipping) if(m_clipping)
g_painter->setClipRect(visibleRect.intersection(getPaddingRect())); g_painter->setClipRect(visibleRect.intersection(getPaddingRect()));
drawChildren(visibleRect, foregroundPane); drawChildren(visibleRect, drawPane);
} }
if(m_clipping) if(m_clipping)
g_painter->resetClipRect(); g_painter->resetClipRect();
} }
void UIWidget::drawSelf(bool foregroundPane) void UIWidget::drawSelf(Fw::DrawPane drawPane)
{ {
if(!foregroundPane) if((drawPane & Fw::ForegroundPane) == 0)
return; return;
// draw style components in order // draw style components in order
@ -88,7 +88,7 @@ void UIWidget::drawSelf(bool foregroundPane)
drawText(m_rect); drawText(m_rect);
} }
void UIWidget::drawChildren(const Rect& visibleRect, bool foregroundPane) void UIWidget::drawChildren(const Rect& visibleRect, Fw::DrawPane drawPane)
{ {
// draw children // draw children
for(const UIWidgetPtr& child : m_children) { for(const UIWidgetPtr& child : m_children) {
@ -107,10 +107,10 @@ void UIWidget::drawChildren(const Rect& visibleRect, bool foregroundPane)
if(child->getOpacity() < oldOpacity) if(child->getOpacity() < oldOpacity)
g_painter->setOpacity(child->getOpacity()); g_painter->setOpacity(child->getOpacity());
child->draw(childVisibleRect, foregroundPane); child->draw(childVisibleRect, drawPane);
// debug draw box // debug draw box
if(foregroundPane && g_ui.isDrawingDebugBoxes()) { if(g_ui.isDrawingDebugBoxes() && drawPane & Fw::ForegroundPane) {
g_painter->setColor(Color::green); g_painter->setColor(Color::green);
g_painter->drawBoundingRect(child->getRect()); g_painter->drawBoundingRect(child->getRect());
} }
@ -497,7 +497,10 @@ void UIWidget::applyStyle(const OTMLNodePtr& styleNode)
callLuaField("onStyleApply", styleNode->tag(), styleNode); callLuaField("onStyleApply", styleNode->tag(), styleNode);
if(m_firstOnStyle) { if(m_firstOnStyle) {
callLuaField("onSetup"); auto self = asUIWidget();
g_eventDispatcher.addEvent([self] {
self->callLuaField("onSetup");
});
// always focus new child // always focus new child
if(isFocusable() && isExplicitlyVisible() && isExplicitlyEnabled()) if(isFocusable() && isExplicitlyVisible() && isExplicitlyEnabled())
focus(); focus();

View File

@ -52,9 +52,9 @@ public:
virtual ~UIWidget(); virtual ~UIWidget();
protected: protected:
virtual void draw(const Rect& visibleRect, bool foregroundPane); virtual void draw(const Rect& visibleRect, Fw::DrawPane drawPane);
virtual void drawSelf(bool foregroundPane); virtual void drawSelf(Fw::DrawPane drawPane);
virtual void drawChildren(const Rect& visibleRect, bool foregroundPane); virtual void drawChildren(const Rect& visibleRect, Fw::DrawPane drawPane);
friend class UIManager; friend class UIManager;

View File

@ -76,11 +76,7 @@ TexturePtr& ThingType::getSpriteMask(int w, int h, int l, int x, int y, int z, i
static Color maskColors[LastMask] = { Color::yellow, Color::red, Color::green, Color::blue }; static Color maskColors[LastMask] = { Color::yellow, Color::red, Color::green, Color::blue };
maskImage->overwriteMask(maskColors[mask]); maskImage->overwriteMask(maskColors[mask]);
maskTexture = TexturePtr(new Texture(maskImage)); maskTexture = TexturePtr(new Texture(maskImage, true));
maskTexture->setSmooth(true);
if(g_graphics.canUseMipmaps())
maskTexture->generateSoftwareMipmaps(maskImage->getPixels());
} }
} }
@ -120,7 +116,7 @@ TexturePtr& ThingType::getTexture(int animationPhase)
Point spritePos = Point(m_dimensions[Width] - w - 1, Point spritePos = Point(m_dimensions[Width] - w - 1,
m_dimensions[Height] - h - 1) * Otc::TILE_PIXELS; m_dimensions[Height] - h - 1) * Otc::TILE_PIXELS;
fullImage->append(framePos + spritePos, spriteImage); fullImage->blit(framePos + spritePos, spriteImage);
} }
} }
} }
@ -139,16 +135,12 @@ TexturePtr& ThingType::getTexture(int animationPhase)
} }
m_texturesFramesRects[animationPhase][frameIndex] = drawRect; m_texturesFramesRects[animationPhase][frameIndex] = drawRect;
m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos; m_texturesFramesOffsets[animationPhase][frameIndex] = drawRect.topLeft() - framePos + Point(1,1);
} }
} }
} }
} }
animationPhaseTexture = TexturePtr(new Texture(fullImage)); animationPhaseTexture = TexturePtr(new Texture(fullImage, true));
animationPhaseTexture->setSmooth(true);
//if(g_graphics.canUseMipmaps())
//animationPhaseTexture->generateSoftwareMipmaps(fullImage->getPixels());
} }
return animationPhaseTexture; return animationPhaseTexture;
} }

View File

@ -51,20 +51,45 @@ void OTClient::init(const std::vector<std::string>& args)
"Compiled by: ", BUILD_COMPILER, "\n", "Compiled by: ", BUILD_COMPILER, "\n",
"Build type: ", BUILD_TYPE, "\n"); "Build type: ", BUILD_TYPE, "\n");
return; return;
} else if(arg == "-help" || arg == "--help" || arg == "-h") { /*
* if(option == "-no-draw-arrays")
m_useDrawArrays = false;
else if(option == "-no-fbos")
m_useFBO = false;
else if(option == "-no-mipmaps")
m_useMipmaps = false;
else if(option == "-no-hardware-mipmaps")
m_useHardwareMipmaps = false;
else if(option == "-no-smooth")
m_useBilinearFiltering = false;
else if(option == "-hardware-buffers")
m_useHardwareBuffers = true;
else if(option == "-no-non-power-of-two-textures")
m_useNonPowerOfTwoTextures = false;
else if(option == "-no-clamp-to-edge")
m_useClampToEdge = false;
else if(option == "-no-backbuffer-cache")
m_cacheBackbuffer = false;
else if(option == "-opengl1")
m_prefferedPainterEngine = Painter_OpenGL1;
else if(option == "-opengl2")
*/
} else if(arg == "-help" || arg == "--help" || arg == "-h" || arg == "-?" || arg == "/?") {
stdext::print( stdext::print(
"Usage: ", args[0], " [options]\n" "Usage: ", args[0], " [options]\n"
"Options:\n" "Options:\n"
" -help Display this information and exit\n" " -help Display this information and exit\n"
" -version Display version and exit\n" " -version Display version and exit\n"
"\n" " \n"
" -no-fbos Disable usage of opengl framebuffer objects\n" " -no-fbos Disable usage of opengl framebuffer objects\n"
" -no-mipmapping Disable texture mipmaping\n" " -no-mipmaps Disable texture mipmaping\n"
" -no-smoothing Disable texture smoothing (bilinear filter)\n" " -no-smooth Disable texture smoothing (bilinear filter)\n"
" -no-hardware-buffering Disable buffering vertex arrays in hardware\n" " -no-non-power-of-two-textures Use only power of two textures\n"
" -realtime-mipmapping Improve framebuffer smoothing quality by\n" " -no-clamp-to-edge Don't use GL_CLAMP_TO_EDGE\n"
" generating mipmaps in realtime when hardware\n" " -no-backbuffer-cache Don't allow backbuffer caching\n"
" mipmap generation implementation is available\n"); " -hardware-buffers Cache vertex arrays in hardware\n"
" -opengl1 Use OpenGL 1.x painter\n"
" -opengl2 Use OpenGL 2.0 painter\n");
return; return;
} else { } else {
stdext::println("Unrecognized option '", arg, "', please see -help for available options list"); stdext::println("Unrecognized option '", arg, "', please see -help for available options list");

View File

@ -24,12 +24,12 @@
#include <framework/otml/otml.h> #include <framework/otml/otml.h>
#include <framework/graphics/graphics.h> #include <framework/graphics/graphics.h>
void UICreature::drawSelf(bool foregroundPane) void UICreature::drawSelf(Fw::DrawPane drawPane)
{ {
if(!foregroundPane) if((drawPane & Fw::ForegroundPane) == 0)
return; return;
UIWidget::drawSelf(foregroundPane); UIWidget::drawSelf(drawPane);
if(m_creature) { if(m_creature) {
Rect drawRect = getPaddingRect(); Rect drawRect = getPaddingRect();

View File

@ -30,7 +30,7 @@
class UICreature : public UIWidget class UICreature : public UIWidget
{ {
public: public:
void drawSelf(bool foregroundPane); void drawSelf(Fw::DrawPane drawPane);
void setCreature(const CreaturePtr& creature) { m_creature = creature; } void setCreature(const CreaturePtr& creature) { m_creature = creature; }
void setFixedCreatureSize(bool fixed) { m_fixedCreatureSize = fixed; } void setFixedCreatureSize(bool fixed) { m_fixedCreatureSize = fixed; }

View File

@ -30,9 +30,9 @@ UIItem::UIItem()
m_dragable = true; m_dragable = true;
} }
void UIItem::drawSelf(bool foregroundPane) void UIItem::drawSelf(Fw::DrawPane drawPane)
{ {
if(!foregroundPane) if((drawPane & Fw::ForegroundPane) == 0)
return; return;
// draw style components in order // draw style components in order

View File

@ -31,7 +31,7 @@ class UIItem : public UIWidget
{ {
public: public:
UIItem(); UIItem();
void drawSelf(bool foregroundPane); void drawSelf(Fw::DrawPane drawPane);
void setItemId(int id); void setItemId(int id);
void setItemCount(int count) { if(m_item) m_item->setCount(count); } void setItemCount(int count) { if(m_item) m_item->setCount(count); }

View File

@ -45,21 +45,25 @@ UIMap::~UIMap()
g_map.removeMapView(m_mapView); g_map.removeMapView(m_mapView);
} }
void UIMap::drawSelf(bool foregroundPane) void UIMap::drawSelf(Fw::DrawPane drawPane)
{ {
if(foregroundPane) { UIWidget::drawSelf(drawPane);
UIWidget::drawSelf(foregroundPane);
if(drawPane & Fw::ForegroundPane) {
// draw map border // draw map border
g_painter->setColor(Color::black); g_painter->setColor(Color::black);
g_painter->drawBoundingRect(m_mapRect.expanded(1)); g_painter->drawBoundingRect(m_mapRect.expanded(1));
g_painter->saveState(); if(drawPane != Fw::BothPanes) {
g_painter->setCompositionMode(Painter::CompositionMode_Replace); g_painter->saveState();
g_painter->setColor(Color::alpha); g_painter->setCompositionMode(Painter::CompositionMode_Replace);
g_painter->drawFilledRect(m_mapRect); g_painter->setColor(Color::alpha);
g_painter->restoreSavedState(); g_painter->drawFilledRect(m_mapRect);
} else { g_painter->restoreSavedState();
}
}
if(drawPane & Fw::BackgroundPane) {
g_painter->setColor(Color::white); g_painter->setColor(Color::white);
m_mapView->draw(m_mapRect); m_mapView->draw(m_mapRect);
} }

View File

@ -35,7 +35,7 @@ public:
UIMap(); UIMap();
~UIMap(); ~UIMap();
void drawSelf(bool foregroundPane); void drawSelf(Fw::DrawPane drawPane);
bool setZoom(int zoom); bool setZoom(int zoom);
bool zoomIn(); bool zoomIn();