Fix memory leaks
* Fix recursive reference memory leak in UIWidget * Make Event/ScheduledEvent memory-leak safe * Fix exit crashs by freeing graphics resources before destroying GL context * Add many asserts to avoid any leak regression
This commit is contained in:
parent
f650b0e5bb
commit
1c7bbaea89
|
@ -213,9 +213,12 @@ SET(framework_SOURCES ${framework_SOURCES}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/fontmanager.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffer.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffermanager.cpp
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/graphics/framebuffermanager.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/glutil.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/glutil.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/graphics.h
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/hardwarebuffer.h
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
|
${CMAKE_CURRENT_LIST_DIR}/graphics/image.cpp
|
||||||
${CMAKE_CURRENT_LIST_DIR}/graphics/image.h
|
${CMAKE_CURRENT_LIST_DIR}/graphics/image.h
|
||||||
|
|
|
@ -116,11 +116,8 @@ void Application::init(const std::vector<std::string>& args)
|
||||||
m_initialized = true;
|
m_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::terminate()
|
void Application::deinit()
|
||||||
{
|
{
|
||||||
if(!m_initialized)
|
|
||||||
return;
|
|
||||||
|
|
||||||
g_lua.callGlobalField("g_app", "onTerminate");
|
g_lua.callGlobalField("g_app", "onTerminate");
|
||||||
|
|
||||||
// hide the window because there is no render anymore
|
// hide the window because there is no render anymore
|
||||||
|
@ -128,6 +125,7 @@ void Application::terminate()
|
||||||
|
|
||||||
// run modules unload events
|
// run modules unload events
|
||||||
g_modules.unloadModules();
|
g_modules.unloadModules();
|
||||||
|
g_modules.clear();
|
||||||
|
|
||||||
// release remaining lua object references
|
// release remaining lua object references
|
||||||
g_lua.collectGarbage();
|
g_lua.collectGarbage();
|
||||||
|
@ -135,19 +133,20 @@ void Application::terminate()
|
||||||
// poll remaining events
|
// poll remaining events
|
||||||
poll();
|
poll();
|
||||||
|
|
||||||
|
// destroy any remaining widget
|
||||||
|
g_ui.terminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Application::terminate()
|
||||||
|
{
|
||||||
|
assert(m_initialized);
|
||||||
|
|
||||||
// terminate network
|
// terminate network
|
||||||
Connection::terminate();
|
Connection::terminate();
|
||||||
|
|
||||||
// terminate graphics
|
|
||||||
g_ui.terminate();
|
|
||||||
g_window.terminate();
|
|
||||||
|
|
||||||
// terminate sound
|
// terminate sound
|
||||||
g_sounds.terminate();
|
g_sounds.terminate();
|
||||||
|
|
||||||
// flush remaining dispatcher events
|
|
||||||
g_eventDispatcher.flush();
|
|
||||||
|
|
||||||
// save configurations
|
// save configurations
|
||||||
g_configs.save();
|
g_configs.save();
|
||||||
|
|
||||||
|
@ -157,15 +156,22 @@ void Application::terminate()
|
||||||
// terminate script environment
|
// terminate script environment
|
||||||
g_lua.terminate();
|
g_lua.terminate();
|
||||||
|
|
||||||
|
// flush remaining dispatcher events
|
||||||
|
g_eventDispatcher.flush();
|
||||||
|
|
||||||
|
// terminate graphics
|
||||||
m_foreground = nullptr;
|
m_foreground = nullptr;
|
||||||
|
g_graphics.terminate();
|
||||||
|
g_window.terminate();
|
||||||
|
|
||||||
g_logger.info("Application ended successfully.");
|
g_logger.info("Application ended successfully.");
|
||||||
|
|
||||||
|
m_terminated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::run()
|
void Application::run()
|
||||||
{
|
{
|
||||||
if(!m_initialized)
|
assert(m_initialized);
|
||||||
return;
|
|
||||||
|
|
||||||
m_stopping = false;
|
m_stopping = false;
|
||||||
m_running = true;
|
m_running = true;
|
||||||
|
|
|
@ -39,6 +39,7 @@ public:
|
||||||
|
|
||||||
virtual void init(const std::vector<std::string>& args);
|
virtual void init(const std::vector<std::string>& args);
|
||||||
virtual void registerLuaFunctions();
|
virtual void registerLuaFunctions();
|
||||||
|
virtual void deinit();
|
||||||
virtual void terminate();
|
virtual void terminate();
|
||||||
virtual void run();
|
virtual void run();
|
||||||
virtual void exit();
|
virtual void exit();
|
||||||
|
@ -53,6 +54,7 @@ public:
|
||||||
|
|
||||||
bool isRunning() { return m_running; }
|
bool isRunning() { return m_running; }
|
||||||
bool isStopping() { return m_stopping; }
|
bool isStopping() { return m_stopping; }
|
||||||
|
bool isTermianted() { return m_terminated; }
|
||||||
bool isOnInputEvent() { return m_onInputEvent; }
|
bool isOnInputEvent() { return m_onInputEvent; }
|
||||||
const std::string& getName() { return m_appName; }
|
const std::string& getName() { return m_appName; }
|
||||||
const std::string& getVersion() { return m_appVersion; }
|
const std::string& getVersion() { return m_appVersion; }
|
||||||
|
@ -76,6 +78,7 @@ protected:
|
||||||
Boolean<false> m_initialized;
|
Boolean<false> m_initialized;
|
||||||
Boolean<false> m_running;
|
Boolean<false> m_running;
|
||||||
Boolean<false> m_stopping;
|
Boolean<false> m_stopping;
|
||||||
|
Boolean<false> m_terminated;
|
||||||
Boolean<false> m_onInputEvent;
|
Boolean<false> m_onInputEvent;
|
||||||
Boolean<false> m_mustRepaint;
|
Boolean<false> m_mustRepaint;
|
||||||
AdaptativeFrameCounter m_backgroundFrameCounter;
|
AdaptativeFrameCounter m_backgroundFrameCounter;
|
||||||
|
|
|
@ -57,6 +57,11 @@ bool ConfigManager::save()
|
||||||
return m_confsDoc->save(m_fileName);
|
return m_confsDoc->save(m_fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConfigManager::clear()
|
||||||
|
{
|
||||||
|
m_confsDoc->clear();
|
||||||
|
}
|
||||||
|
|
||||||
void ConfigManager::set(const std::string& key, const std::string& value)
|
void ConfigManager::set(const std::string& key, const std::string& value)
|
||||||
{
|
{
|
||||||
if(key == "") {
|
if(key == "") {
|
||||||
|
|
|
@ -32,6 +32,7 @@ public:
|
||||||
ConfigManager();
|
ConfigManager();
|
||||||
bool load(const std::string& file);
|
bool load(const std::string& file);
|
||||||
bool save();
|
bool save();
|
||||||
|
void clear();
|
||||||
|
|
||||||
void set(const std::string& key, const std::string& value);
|
void set(const std::string& key, const std::string& value);
|
||||||
void setList(const std::string& key, const std::vector<std::string>& list);
|
void setList(const std::string& key, const std::vector<std::string>& list);
|
||||||
|
|
|
@ -32,8 +32,12 @@ void EventDispatcher::flush()
|
||||||
while(!m_eventList.empty())
|
while(!m_eventList.empty())
|
||||||
poll();
|
poll();
|
||||||
|
|
||||||
while(!m_scheduledEventList.empty())
|
while(!m_scheduledEventList.empty()) {
|
||||||
|
ScheduledEventPtr scheduledEvent = m_scheduledEventList.top();
|
||||||
|
scheduledEvent->cancel();
|
||||||
m_scheduledEventList.pop();
|
m_scheduledEventList.pop();
|
||||||
|
}
|
||||||
|
m_disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventDispatcher::poll()
|
void EventDispatcher::poll()
|
||||||
|
@ -77,6 +81,9 @@ void EventDispatcher::poll()
|
||||||
|
|
||||||
ScheduledEventPtr EventDispatcher::scheduleEvent(const std::function<void()>& callback, int delay)
|
ScheduledEventPtr EventDispatcher::scheduleEvent(const std::function<void()>& callback, int delay)
|
||||||
{
|
{
|
||||||
|
if(m_disabled)
|
||||||
|
return ScheduledEventPtr(new ScheduledEvent(nullptr, delay, 1));
|
||||||
|
|
||||||
assert(delay >= 0);
|
assert(delay >= 0);
|
||||||
ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 1));
|
ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 1));
|
||||||
m_scheduledEventList.push(scheduledEvent);
|
m_scheduledEventList.push(scheduledEvent);
|
||||||
|
@ -85,6 +92,9 @@ ScheduledEventPtr EventDispatcher::scheduleEvent(const std::function<void()>& ca
|
||||||
|
|
||||||
ScheduledEventPtr EventDispatcher::cycleEvent(const std::function<void()>& callback, int delay)
|
ScheduledEventPtr EventDispatcher::cycleEvent(const std::function<void()>& callback, int delay)
|
||||||
{
|
{
|
||||||
|
if(m_disabled)
|
||||||
|
return ScheduledEventPtr(new ScheduledEvent(nullptr, delay, 0));
|
||||||
|
|
||||||
assert(delay > 0);
|
assert(delay > 0);
|
||||||
ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 0));
|
ScheduledEventPtr scheduledEvent(new ScheduledEvent(callback, delay, 0));
|
||||||
m_scheduledEventList.push(scheduledEvent);
|
m_scheduledEventList.push(scheduledEvent);
|
||||||
|
@ -93,6 +103,9 @@ ScheduledEventPtr EventDispatcher::cycleEvent(const std::function<void()>& callb
|
||||||
|
|
||||||
EventPtr EventDispatcher::addEvent(const std::function<void()>& callback, bool pushFront)
|
EventPtr EventDispatcher::addEvent(const std::function<void()>& callback, bool pushFront)
|
||||||
{
|
{
|
||||||
|
if(m_disabled)
|
||||||
|
return EventPtr(new Event(nullptr));
|
||||||
|
|
||||||
EventPtr event(new Event(callback));
|
EventPtr event(new Event(callback));
|
||||||
// front pushing is a way to execute an event before others
|
// front pushing is a way to execute an event before others
|
||||||
if(pushFront) {
|
if(pushFront) {
|
||||||
|
|
|
@ -31,14 +31,24 @@ class Event : public LuaObject
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Event(const std::function<void()>& callback) : m_callback(callback), m_canceled(false), m_executed(false) { }
|
Event(const std::function<void()>& callback) : m_callback(callback), m_canceled(false), m_executed(false) { }
|
||||||
|
virtual ~Event() {
|
||||||
|
// assure that we lost callback refs
|
||||||
|
assert(m_callback == nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
virtual void execute() {
|
virtual void execute() {
|
||||||
if(!m_canceled && !m_executed && m_callback) {
|
if(!m_canceled && !m_executed && m_callback) {
|
||||||
m_callback();
|
m_callback();
|
||||||
m_executed = true;
|
m_executed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reset callback to free object refs
|
||||||
|
m_callback = nullptr;
|
||||||
|
}
|
||||||
|
void cancel() {
|
||||||
|
m_canceled = true;
|
||||||
|
m_callback = nullptr;
|
||||||
}
|
}
|
||||||
void cancel() { m_canceled = true; }
|
|
||||||
|
|
||||||
bool isCanceled() { return m_canceled; }
|
bool isCanceled() { return m_canceled; }
|
||||||
bool isExecuted() { return m_executed; }
|
bool isExecuted() { return m_executed; }
|
||||||
|
@ -63,17 +73,21 @@ public:
|
||||||
if(!m_canceled && m_callback && (m_maxCycles == 0 || m_cyclesExecuted < m_maxCycles)) {
|
if(!m_canceled && m_callback && (m_maxCycles == 0 || m_cyclesExecuted < m_maxCycles)) {
|
||||||
m_callback();
|
m_callback();
|
||||||
m_executed = true;
|
m_executed = true;
|
||||||
|
// callback may be used in the next cycle
|
||||||
|
} else {
|
||||||
|
// reset callback to free object refs
|
||||||
|
m_callback = nullptr;
|
||||||
}
|
}
|
||||||
m_cyclesExecuted++;
|
m_cyclesExecuted++;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nextCycle() {
|
bool nextCycle() {
|
||||||
if(m_canceled)
|
if(m_callback && !m_canceled && (m_maxCycles == 0 || m_cyclesExecuted < m_maxCycles)) {
|
||||||
return false;
|
|
||||||
if(m_maxCycles == 0 || m_cyclesExecuted < m_maxCycles) {
|
|
||||||
m_ticks += m_delay;
|
m_ticks += m_delay;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
// reset callback to free object refs
|
||||||
|
m_callback = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,6 +123,7 @@ public:
|
||||||
private:
|
private:
|
||||||
std::list<EventPtr> m_eventList;
|
std::list<EventPtr> m_eventList;
|
||||||
int m_pollEventsSize;
|
int m_pollEventsSize;
|
||||||
|
Boolean<false> m_disabled;
|
||||||
std::priority_queue<ScheduledEventPtr, std::vector<ScheduledEventPtr>, lessScheduledEvent> m_scheduledEventList;
|
std::priority_queue<ScheduledEventPtr, std::vector<ScheduledEventPtr>, lessScheduledEvent> m_scheduledEventList;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,12 @@
|
||||||
|
|
||||||
ModuleManager g_modules;
|
ModuleManager g_modules;
|
||||||
|
|
||||||
|
void ModuleManager::clear()
|
||||||
|
{
|
||||||
|
m_modules.clear();
|
||||||
|
m_autoLoadModules.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void ModuleManager::discoverModules()
|
void ModuleManager::discoverModules()
|
||||||
{
|
{
|
||||||
// remove modules that are not loaded
|
// remove modules that are not loaded
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
class ModuleManager
|
class ModuleManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
void clear();
|
||||||
|
|
||||||
void discoverModulesPath();
|
void discoverModulesPath();
|
||||||
void discoverModules();
|
void discoverModules();
|
||||||
void autoLoadModules(int maxPriority);
|
void autoLoadModules(int maxPriority);
|
||||||
|
|
|
@ -27,11 +27,13 @@
|
||||||
#include "glutil.h"
|
#include "glutil.h"
|
||||||
|
|
||||||
class Texture;
|
class Texture;
|
||||||
|
class TextureManager;
|
||||||
class Image;
|
class Image;
|
||||||
class AnimatedTexture;
|
class AnimatedTexture;
|
||||||
class BitmapFont;
|
class BitmapFont;
|
||||||
class CachedText;
|
class CachedText;
|
||||||
class FrameBuffer;
|
class FrameBuffer;
|
||||||
|
class FrameBufferManager;
|
||||||
class Shader;
|
class Shader;
|
||||||
class ShaderProgram;
|
class ShaderProgram;
|
||||||
class PainterShaderProgram;
|
class PainterShaderProgram;
|
||||||
|
|
|
@ -32,10 +32,10 @@ FontManager::FontManager()
|
||||||
m_defaultFont = BitmapFontPtr(new BitmapFont("emptyfont"));
|
m_defaultFont = BitmapFontPtr(new BitmapFont("emptyfont"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontManager::releaseFonts()
|
void FontManager::terminate()
|
||||||
{
|
{
|
||||||
m_defaultFont.reset();
|
|
||||||
m_fonts.clear();
|
m_fonts.clear();
|
||||||
|
m_defaultFont = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FontManager::importFont(std::string fontFile)
|
bool FontManager::importFont(std::string fontFile)
|
||||||
|
|
|
@ -30,10 +30,8 @@ class FontManager
|
||||||
public:
|
public:
|
||||||
FontManager();
|
FontManager();
|
||||||
|
|
||||||
/// Release fonts references, thus making possible to destruct them
|
void terminate();
|
||||||
void releaseFonts();
|
|
||||||
|
|
||||||
/// Import a font from .otfont file
|
|
||||||
bool importFont(std::string fontFile);
|
bool importFont(std::string fontFile);
|
||||||
|
|
||||||
bool fontExists(const std::string& fontName);
|
bool fontExists(const std::string& fontName);
|
||||||
|
|
|
@ -23,7 +23,9 @@
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "graphics.h"
|
#include "graphics.h"
|
||||||
#include "texture.h"
|
#include "texture.h"
|
||||||
|
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
#include <framework/application.h>
|
||||||
|
|
||||||
uint FrameBuffer::boundFbo = 0;
|
uint FrameBuffer::boundFbo = 0;
|
||||||
|
|
||||||
|
@ -32,12 +34,6 @@ FrameBuffer::FrameBuffer()
|
||||||
internalCreate();
|
internalCreate();
|
||||||
}
|
}
|
||||||
|
|
||||||
FrameBuffer::FrameBuffer(const Size& size)
|
|
||||||
{
|
|
||||||
internalCreate();
|
|
||||||
resize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FrameBuffer::internalCreate()
|
void FrameBuffer::internalCreate()
|
||||||
{
|
{
|
||||||
m_prevBoundFbo = 0;
|
m_prevBoundFbo = 0;
|
||||||
|
@ -51,14 +47,14 @@ void FrameBuffer::internalCreate()
|
||||||
|
|
||||||
FrameBuffer::~FrameBuffer()
|
FrameBuffer::~FrameBuffer()
|
||||||
{
|
{
|
||||||
if(m_fbo != 0)
|
assert(!g_app->isTermianted());
|
||||||
|
if(g_graphics.ok() && m_fbo != 0)
|
||||||
glDeleteFramebuffers(1, &m_fbo);
|
glDeleteFramebuffers(1, &m_fbo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FrameBuffer::resize(const Size& size)
|
void FrameBuffer::resize(const Size& size)
|
||||||
{
|
{
|
||||||
if(!size.isValid())
|
assert(size.isValid());
|
||||||
return;
|
|
||||||
|
|
||||||
if(m_texture && m_texture->getSize() == size)
|
if(m_texture && m_texture->getSize() == size)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -28,9 +28,12 @@
|
||||||
|
|
||||||
class FrameBuffer
|
class FrameBuffer
|
||||||
{
|
{
|
||||||
public:
|
protected:
|
||||||
FrameBuffer();
|
FrameBuffer();
|
||||||
FrameBuffer(const Size& size);
|
|
||||||
|
friend class FrameBufferManager;
|
||||||
|
|
||||||
|
public:
|
||||||
virtual ~FrameBuffer();
|
virtual ~FrameBuffer();
|
||||||
|
|
||||||
void resize(const Size& size);
|
void resize(const Size& size);
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2012 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 "framebuffermanager.h"
|
||||||
|
|
||||||
|
FrameBufferManager g_framebuffers;
|
||||||
|
|
||||||
|
void FrameBufferManager::init()
|
||||||
|
{
|
||||||
|
m_temporaryFramebuffer = FrameBufferPtr(new FrameBuffer());
|
||||||
|
}
|
||||||
|
|
||||||
|
void FrameBufferManager::terminate()
|
||||||
|
{
|
||||||
|
m_framebuffers.clear();
|
||||||
|
m_temporaryFramebuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
FrameBufferPtr FrameBufferManager::createFrameBuffer()
|
||||||
|
{
|
||||||
|
FrameBufferPtr fbo = FrameBufferPtr(new FrameBuffer());
|
||||||
|
m_framebuffers.push_back(fbo);
|
||||||
|
return fbo;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2012 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 FRAMEBUFFERMANAGER_H
|
||||||
|
#define FRAMEBUFFERMANAGER_H
|
||||||
|
|
||||||
|
#include "framebuffer.h"
|
||||||
|
|
||||||
|
class FrameBufferManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
void terminate();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
FrameBufferPtr createFrameBuffer();
|
||||||
|
const FrameBufferPtr& getTemporaryFrameBuffer() { return m_temporaryFramebuffer; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
FrameBufferPtr m_temporaryFramebuffer;
|
||||||
|
std::vector<FrameBufferPtr> m_framebuffers;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern FrameBufferManager g_framebuffers;
|
||||||
|
|
||||||
|
#endif
|
|
@ -33,6 +33,8 @@
|
||||||
|
|
||||||
#include <framework/graphics/graphics.h>
|
#include <framework/graphics/graphics.h>
|
||||||
#include <framework/graphics/texture.h>
|
#include <framework/graphics/texture.h>
|
||||||
|
#include "texturemanager.h"
|
||||||
|
#include "framebuffermanager.h"
|
||||||
#include <framework/platform/platformwindow.h>
|
#include <framework/platform/platformwindow.h>
|
||||||
|
|
||||||
Graphics g_graphics;
|
Graphics g_graphics;
|
||||||
|
@ -88,13 +90,19 @@ void Graphics::init()
|
||||||
m_alphaBits = 0;
|
m_alphaBits = 0;
|
||||||
glGetIntegerv(GL_ALPHA_BITS, &m_alphaBits);
|
glGetIntegerv(GL_ALPHA_BITS, &m_alphaBits);
|
||||||
|
|
||||||
|
m_ok = true;
|
||||||
|
|
||||||
selectPainterEngine(m_prefferedPainterEngine);
|
selectPainterEngine(m_prefferedPainterEngine);
|
||||||
m_emptyTexture = TexturePtr(new Texture);
|
|
||||||
|
g_textures.init();
|
||||||
|
g_framebuffers.init();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Graphics::terminate()
|
void Graphics::terminate()
|
||||||
{
|
{
|
||||||
g_fonts.releaseFonts();
|
g_fonts.terminate();
|
||||||
|
g_framebuffers.terminate();
|
||||||
|
g_textures.terminate();
|
||||||
|
|
||||||
#ifdef PAINTER_OGL2
|
#ifdef PAINTER_OGL2
|
||||||
if(g_painterOGL2) {
|
if(g_painterOGL2) {
|
||||||
|
@ -112,7 +120,7 @@ void Graphics::terminate()
|
||||||
|
|
||||||
g_painter = nullptr;
|
g_painter = nullptr;
|
||||||
|
|
||||||
m_emptyTexture.reset();
|
m_ok = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Graphics::parseOption(const std::string& option)
|
bool Graphics::parseOption(const std::string& option)
|
||||||
|
|
|
@ -51,13 +51,13 @@ public:
|
||||||
|
|
||||||
int getMaxTextureSize() { return m_maxTextureSize; }
|
int getMaxTextureSize() { return m_maxTextureSize; }
|
||||||
const Size& getViewportSize() { return m_viewportSize; }
|
const Size& getViewportSize() { return m_viewportSize; }
|
||||||
TexturePtr& getEmptyTexture() { return m_emptyTexture; }
|
|
||||||
|
|
||||||
std::string getVendor() { return (const char*)glGetString(GL_VENDOR); }
|
std::string getVendor() { return (const char*)glGetString(GL_VENDOR); }
|
||||||
std::string getRenderer() { return (const char*)glGetString(GL_RENDERER); }
|
std::string getRenderer() { return (const char*)glGetString(GL_RENDERER); }
|
||||||
std::string getVersion() { return (const char*)glGetString(GL_VERSION); }
|
std::string getVersion() { return (const char*)glGetString(GL_VERSION); }
|
||||||
std::string getExtensions() { return (const char*)glGetString(GL_EXTENSIONS); }
|
std::string getExtensions() { return (const char*)glGetString(GL_EXTENSIONS); }
|
||||||
|
|
||||||
|
bool ok() { return m_ok; }
|
||||||
bool canUseDrawArrays();
|
bool canUseDrawArrays();
|
||||||
bool canUseShaders();
|
bool canUseShaders();
|
||||||
bool canUseFBO();
|
bool canUseFBO();
|
||||||
|
@ -72,10 +72,10 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Size m_viewportSize;
|
Size m_viewportSize;
|
||||||
TexturePtr m_emptyTexture;
|
|
||||||
|
|
||||||
int m_maxTextureSize;
|
int m_maxTextureSize;
|
||||||
int m_alphaBits;
|
int m_alphaBits;
|
||||||
|
Boolean<false> m_ok;
|
||||||
Boolean<true> m_useDrawArrays;
|
Boolean<true> m_useDrawArrays;
|
||||||
Boolean<true> m_useFBO;
|
Boolean<true> m_useFBO;
|
||||||
Boolean<false> m_useHardwareBuffers;
|
Boolean<false> m_useHardwareBuffers;
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010-2012 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 "hardwarebuffer.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
|
#include <framework/core/logger.h>
|
||||||
|
|
||||||
|
HardwareBuffer::HardwareBuffer(Type type)
|
||||||
|
{
|
||||||
|
m_type = type;
|
||||||
|
m_id = 0;
|
||||||
|
glGenBuffers(1, &m_id);
|
||||||
|
if(!m_id)
|
||||||
|
g_logger.fatal("Unable to create hardware buffer.");
|
||||||
|
}
|
||||||
|
|
||||||
|
HardwareBuffer::~HardwareBuffer()
|
||||||
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
|
if(g_graphics.ok())
|
||||||
|
glDeleteBuffers(1, &m_id);
|
||||||
|
}
|
|
@ -40,15 +40,8 @@ public:
|
||||||
DynamicDraw = GL_DYNAMIC_DRAW
|
DynamicDraw = GL_DYNAMIC_DRAW
|
||||||
};
|
};
|
||||||
|
|
||||||
HardwareBuffer(Type type) {
|
HardwareBuffer(Type type);
|
||||||
m_type = type;
|
~HardwareBuffer();
|
||||||
m_id = 0;
|
|
||||||
glGenBuffers(1, &m_id);
|
|
||||||
assert(m_id != 0);
|
|
||||||
}
|
|
||||||
~HardwareBuffer() {
|
|
||||||
glDeleteBuffers(1, &m_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void bind() { glBindBuffer(m_type, m_id); }
|
void bind() { glBindBuffer(m_type, m_id); }
|
||||||
static void unbind(Type type) { glBindBuffer(type, 0); }
|
static void unbind(Type type) { glBindBuffer(type, 0); }
|
||||||
|
|
|
@ -48,12 +48,6 @@ PainterOGL2::PainterOGL2()
|
||||||
PainterShaderProgram::release();
|
PainterShaderProgram::release();
|
||||||
}
|
}
|
||||||
|
|
||||||
PainterOGL2::~PainterOGL2()
|
|
||||||
{
|
|
||||||
m_drawTexturedProgram = nullptr;
|
|
||||||
m_drawSolidColorProgram = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PainterOGL2::bind()
|
void PainterOGL2::bind()
|
||||||
{
|
{
|
||||||
Painter::bind();
|
Painter::bind();
|
||||||
|
|
|
@ -36,7 +36,6 @@ class PainterOGL2 : public Painter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PainterOGL2();
|
PainterOGL2();
|
||||||
~PainterOGL2();
|
|
||||||
|
|
||||||
void bind();
|
void bind();
|
||||||
void unbind();
|
void unbind();
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "shader.h"
|
#include "shader.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
#include <framework/core/resourcemanager.h>
|
#include <framework/core/resourcemanager.h>
|
||||||
|
|
||||||
Shader::Shader(Shader::ShaderType shaderType)
|
Shader::Shader(Shader::ShaderType shaderType)
|
||||||
|
@ -41,7 +44,9 @@ Shader::Shader(Shader::ShaderType shaderType)
|
||||||
|
|
||||||
Shader::~Shader()
|
Shader::~Shader()
|
||||||
{
|
{
|
||||||
glDeleteShader(m_shaderId);
|
assert(!g_app->isTermianted());
|
||||||
|
if(g_graphics.ok())
|
||||||
|
glDeleteShader(m_shaderId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shader::compileSourceCode(const std::string& sourceCode)
|
bool Shader::compileSourceCode(const std::string& sourceCode)
|
||||||
|
|
|
@ -21,6 +21,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "shaderprogram.h"
|
#include "shaderprogram.h"
|
||||||
|
#include "graphics.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
|
|
||||||
GLuint ShaderProgram::m_currentProgram = 0;
|
GLuint ShaderProgram::m_currentProgram = 0;
|
||||||
|
|
||||||
|
@ -35,7 +38,9 @@ ShaderProgram::ShaderProgram()
|
||||||
|
|
||||||
ShaderProgram::~ShaderProgram()
|
ShaderProgram::~ShaderProgram()
|
||||||
{
|
{
|
||||||
glDeleteProgram(m_programId);
|
assert(!g_app->isTermianted());
|
||||||
|
if(g_graphics.ok())
|
||||||
|
glDeleteProgram(m_programId);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShaderProgram::addShader(const ShaderPtr& shader) {
|
bool ShaderProgram::addShader(const ShaderPtr& shader) {
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include "framebuffer.h"
|
#include "framebuffer.h"
|
||||||
#include "image.h"
|
#include "image.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
|
|
||||||
Texture::Texture()
|
Texture::Texture()
|
||||||
{
|
{
|
||||||
m_id = 0;
|
m_id = 0;
|
||||||
|
@ -77,8 +79,9 @@ Texture::Texture(const ImagePtr& image, bool buildMipmaps)
|
||||||
|
|
||||||
Texture::~Texture()
|
Texture::~Texture()
|
||||||
{
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
// free texture from gl memory
|
// free texture from gl memory
|
||||||
if(m_id > 0)
|
if(g_graphics.ok() && m_id != 0)
|
||||||
glDeleteTextures(1, &m_id);
|
glDeleteTextures(1, &m_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,26 @@
|
||||||
|
|
||||||
TextureManager g_textures;
|
TextureManager g_textures;
|
||||||
|
|
||||||
|
void TextureManager::init()
|
||||||
|
{
|
||||||
|
m_emptyTexture = TexturePtr(new Texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TextureManager::terminate()
|
||||||
|
{
|
||||||
|
#ifndef NDEBUG
|
||||||
|
// check for leaks
|
||||||
|
int refs = 0;
|
||||||
|
for(const auto& it : m_textures)
|
||||||
|
if(it.second.use_count() > 1)
|
||||||
|
refs++;
|
||||||
|
if(refs > 0)
|
||||||
|
g_logger.debug(stdext::format("%d textures references left", refs));
|
||||||
|
#endif
|
||||||
|
m_textures.clear();
|
||||||
|
m_emptyTexture = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
TexturePtr TextureManager::getTexture(const std::string& fileName)
|
TexturePtr TextureManager::getTexture(const std::string& fileName)
|
||||||
{
|
{
|
||||||
TexturePtr texture;
|
TexturePtr texture;
|
||||||
|
@ -59,7 +79,7 @@ TexturePtr TextureManager::getTexture(const std::string& fileName)
|
||||||
texture = loadPNG(fin);
|
texture = loadPNG(fin);
|
||||||
} catch(stdext::exception& e) {
|
} catch(stdext::exception& e) {
|
||||||
g_logger.error(stdext::format("unable to load texture '%s': %s", fileName, e.what()));
|
g_logger.error(stdext::format("unable to load texture '%s': %s", fileName, e.what()));
|
||||||
texture = g_graphics.getEmptyTexture();
|
texture = g_textures.getEmptyTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(texture)
|
if(texture)
|
||||||
|
|
|
@ -28,12 +28,17 @@
|
||||||
class TextureManager
|
class TextureManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TexturePtr getTexture(const std::string& fileName);
|
void init();
|
||||||
|
void terminate();
|
||||||
|
|
||||||
static TexturePtr loadPNG(std::stringstream& file);
|
TexturePtr getTexture(const std::string& fileName);
|
||||||
|
const TexturePtr& getEmptyTexture() { return m_emptyTexture; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
TexturePtr loadPNG(std::stringstream& file);
|
||||||
|
|
||||||
std::unordered_map<std::string, TextureWeakPtr> m_textures;
|
std::unordered_map<std::string, TextureWeakPtr> m_textures;
|
||||||
|
TexturePtr m_emptyTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern TextureManager g_textures;
|
extern TextureManager g_textures;
|
||||||
|
|
|
@ -35,6 +35,8 @@ LuaInterface::LuaInterface()
|
||||||
L = nullptr;
|
L = nullptr;
|
||||||
m_cppCallbackDepth = 0;
|
m_cppCallbackDepth = 0;
|
||||||
m_weakTableRef = 0;
|
m_weakTableRef = 0;
|
||||||
|
m_totalObjRefs = 0;
|
||||||
|
m_totalFuncRefs = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaInterface::~LuaInterface()
|
LuaInterface::~LuaInterface()
|
||||||
|
@ -64,6 +66,8 @@ void LuaInterface::terminate()
|
||||||
{
|
{
|
||||||
// close lua state, it will release all objects
|
// close lua state, it will release all objects
|
||||||
closeLuaState();
|
closeLuaState();
|
||||||
|
assert(m_totalFuncRefs == 0);
|
||||||
|
assert(m_totalObjRefs == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LuaInterface::registerSingletonClass(const std::string& className)
|
void LuaInterface::registerSingletonClass(const std::string& className)
|
||||||
|
@ -280,6 +284,7 @@ int LuaInterface::luaObjectCollectEvent(LuaInterface* lua)
|
||||||
|
|
||||||
// resets pointer to decrease object use count
|
// resets pointer to decrease object use count
|
||||||
objPtr->reset();
|
objPtr->reset();
|
||||||
|
g_lua.m_totalObjRefs--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,6 +608,7 @@ int LuaInterface::luaCollectCppFunction(lua_State* L)
|
||||||
auto funcPtr = static_cast<LuaCppFunctionPtr*>(g_lua.popUserdata());
|
auto funcPtr = static_cast<LuaCppFunctionPtr*>(g_lua.popUserdata());
|
||||||
assert(funcPtr);
|
assert(funcPtr);
|
||||||
funcPtr->reset();
|
funcPtr->reset();
|
||||||
|
g_lua.m_totalFuncRefs--;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1033,6 +1039,7 @@ void LuaInterface::pushObject(const LuaObjectPtr& obj)
|
||||||
{
|
{
|
||||||
// fills a new userdata with a new LuaObjectPtr pointer
|
// fills a new userdata with a new LuaObjectPtr pointer
|
||||||
new(newUserdata(sizeof(LuaObjectPtr))) LuaObjectPtr(obj);
|
new(newUserdata(sizeof(LuaObjectPtr))) LuaObjectPtr(obj);
|
||||||
|
m_totalObjRefs++;
|
||||||
|
|
||||||
// set the userdata metatable
|
// set the userdata metatable
|
||||||
getGlobal(stdext::format("%s_mt", obj->getClassName()));
|
getGlobal(stdext::format("%s_mt", obj->getClassName()));
|
||||||
|
@ -1050,6 +1057,7 @@ void LuaInterface::pushCppFunction(const LuaCppFunction& func)
|
||||||
{
|
{
|
||||||
// create a pointer to func (this pointer will hold the function existence)
|
// create a pointer to func (this pointer will hold the function existence)
|
||||||
new(newUserdata(sizeof(LuaCppFunctionPtr))) LuaCppFunctionPtr(new LuaCppFunction(func));
|
new(newUserdata(sizeof(LuaCppFunctionPtr))) LuaCppFunctionPtr(new LuaCppFunction(func));
|
||||||
|
m_totalFuncRefs++;
|
||||||
|
|
||||||
// sets the userdata __gc metamethod, needed to free the function pointer when it gets collected
|
// sets the userdata __gc metamethod, needed to free the function pointer when it gets collected
|
||||||
newTable();
|
newTable();
|
||||||
|
|
|
@ -329,6 +329,8 @@ private:
|
||||||
lua_State* L;
|
lua_State* L;
|
||||||
int m_weakTableRef;
|
int m_weakTableRef;
|
||||||
int m_cppCallbackDepth;
|
int m_cppCallbackDepth;
|
||||||
|
int m_totalObjRefs;
|
||||||
|
int m_totalFuncRefs;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern LuaInterface g_lua;
|
extern LuaInterface g_lua;
|
||||||
|
|
|
@ -23,12 +23,15 @@
|
||||||
#include "luaobject.h"
|
#include "luaobject.h"
|
||||||
#include "luainterface.h"
|
#include "luainterface.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
|
|
||||||
LuaObject::LuaObject() : m_fieldsTableRef(-1)
|
LuaObject::LuaObject() : m_fieldsTableRef(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
LuaObject::~LuaObject()
|
LuaObject::~LuaObject()
|
||||||
{
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
releaseLuaFieldsTable();
|
releaseLuaFieldsTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
|
|
||||||
#include "connection.h"
|
#include "connection.h"
|
||||||
|
|
||||||
|
#include <framework/application.h>
|
||||||
#include <framework/core/eventdispatcher.h>
|
#include <framework/core/eventdispatcher.h>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
|
|
||||||
|
@ -40,6 +41,7 @@ Connection::Connection() :
|
||||||
|
|
||||||
Connection::~Connection()
|
Connection::~Connection()
|
||||||
{
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,9 @@ void UIManager::terminate()
|
||||||
m_draggingWidget = nullptr;
|
m_draggingWidget = nullptr;
|
||||||
m_hoveredWidget = nullptr;
|
m_hoveredWidget = nullptr;
|
||||||
m_pressedWidget = nullptr;
|
m_pressedWidget = nullptr;
|
||||||
|
m_styles.clear();
|
||||||
|
m_destroyedWidgets.clear();
|
||||||
|
m_checkEvent = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void UIManager::render(Fw::DrawPane drawPane)
|
void UIManager::render(Fw::DrawPane drawPane)
|
||||||
|
@ -266,22 +269,19 @@ void UIManager::onWidgetDestroy(const UIWidgetPtr& widget)
|
||||||
if(m_draggingWidget == widget)
|
if(m_draggingWidget == widget)
|
||||||
updateDraggingWidget(nullptr);
|
updateDraggingWidget(nullptr);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifndef DEBUG
|
||||||
static UIWidgetList destroyedWidgets;
|
if(widget == m_rootWidget || !m_rootWidget)
|
||||||
static ScheduledEventPtr checkEvent;
|
|
||||||
|
|
||||||
if(widget == m_rootWidget)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
destroyedWidgets.push_back(widget);
|
m_destroyedWidgets.push_back(widget);
|
||||||
|
|
||||||
if(checkEvent && !checkEvent->isExecuted())
|
if(m_checkEvent && !m_checkEvent->isExecuted())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
checkEvent = g_eventDispatcher.scheduleEvent([] {
|
m_checkEvent = g_eventDispatcher.scheduleEvent([] {
|
||||||
g_lua.collectGarbage();
|
g_lua.collectGarbage();
|
||||||
UIWidgetList backupList = destroyedWidgets;
|
UIWidgetList backupList = m_destroyedWidgets;
|
||||||
destroyedWidgets.clear();
|
m_destroyedWidgets.clear();
|
||||||
g_eventDispatcher.scheduleEvent([backupList] {
|
g_eventDispatcher.scheduleEvent([backupList] {
|
||||||
g_lua.collectGarbage();
|
g_lua.collectGarbage();
|
||||||
for(const UIWidgetPtr& widget : backupList) {
|
for(const UIWidgetPtr& widget : backupList) {
|
||||||
|
|
|
@ -82,6 +82,8 @@ private:
|
||||||
Boolean<false> m_hoverUpdateScheduled;
|
Boolean<false> m_hoverUpdateScheduled;
|
||||||
Boolean<false> m_drawDebugBoxes;
|
Boolean<false> m_drawDebugBoxes;
|
||||||
std::unordered_map<std::string, OTMLNodePtr> m_styles;
|
std::unordered_map<std::string, OTMLNodePtr> m_styles;
|
||||||
|
UIWidgetList m_destroyedWidgets;
|
||||||
|
ScheduledEventPtr m_checkEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern UIManager g_ui;
|
extern UIManager g_ui;
|
||||||
|
|
|
@ -46,6 +46,7 @@ UIWidget::UIWidget()
|
||||||
|
|
||||||
UIWidget::~UIWidget()
|
UIWidget::~UIWidget()
|
||||||
{
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
if(!m_destroyed)
|
if(!m_destroyed)
|
||||||
g_logger.warning(stdext::format("widget '%s' was not explicitly destroyed", m_id));
|
g_logger.warning(stdext::format("widget '%s' was not explicitly destroyed", m_id));
|
||||||
|
|
|
@ -28,6 +28,7 @@ int main(int argc, const char* argv[])
|
||||||
OTClient app;
|
OTClient app;
|
||||||
app.init(args);
|
app.init(args);
|
||||||
app.run();
|
app.run();
|
||||||
|
app.deinit();
|
||||||
app.terminate();
|
app.terminate();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
#include <framework/graphics/paintershaderprogram.h>
|
#include <framework/graphics/paintershaderprogram.h>
|
||||||
#include <framework/graphics/painterogl2_shadersources.h>
|
#include <framework/graphics/painterogl2_shadersources.h>
|
||||||
#include <framework/graphics/texturemanager.h>
|
#include <framework/graphics/texturemanager.h>
|
||||||
#include <framework/graphics/framebuffer.h>
|
#include <framework/graphics/framebuffermanager.h>
|
||||||
#include "spritemanager.h"
|
#include "spritemanager.h"
|
||||||
|
|
||||||
Creature::Creature() : Thing()
|
Creature::Creature() : Thing()
|
||||||
|
@ -161,10 +161,8 @@ void Creature::internalDrawOutfit(const Point& dest, float scaleFactor, bool ani
|
||||||
void Creature::drawOutfit(const Rect& destRect, bool resize)
|
void Creature::drawOutfit(const Rect& destRect, bool resize)
|
||||||
{
|
{
|
||||||
if(g_graphics.canUseFBO()) {
|
if(g_graphics.canUseFBO()) {
|
||||||
static FrameBufferPtr outfitBuffer;
|
const FrameBufferPtr& outfitBuffer = g_framebuffers.getTemporaryFrameBuffer();
|
||||||
if(!outfitBuffer)
|
outfitBuffer->resize(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS));
|
||||||
outfitBuffer = FrameBufferPtr(new FrameBuffer(Size(2*Otc::TILE_PIXELS, 2*Otc::TILE_PIXELS)));
|
|
||||||
|
|
||||||
outfitBuffer->bind();
|
outfitBuffer->bind();
|
||||||
g_painter->setAlphaWriting(true);
|
g_painter->setAlphaWriting(true);
|
||||||
g_painter->clear(Color::alpha);
|
g_painter->clear(Color::alpha);
|
||||||
|
|
|
@ -62,5 +62,6 @@ typedef std::shared_ptr<StaticText> StaticTextPtr;
|
||||||
typedef std::shared_ptr<ItemShader> ItemShaderPtr;
|
typedef std::shared_ptr<ItemShader> ItemShaderPtr;
|
||||||
|
|
||||||
typedef std::vector<ThingPtr> ThingList;
|
typedef std::vector<ThingPtr> ThingList;
|
||||||
|
typedef std::vector<ThingType> ThingTypeList;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -22,8 +22,6 @@
|
||||||
|
|
||||||
#include "mapview.h"
|
#include "mapview.h"
|
||||||
|
|
||||||
#include <framework/graphics/graphics.h>
|
|
||||||
#include <framework/graphics/framebuffer.h>
|
|
||||||
#include "creature.h"
|
#include "creature.h"
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "tile.h"
|
#include "tile.h"
|
||||||
|
@ -31,7 +29,11 @@
|
||||||
#include "animatedtext.h"
|
#include "animatedtext.h"
|
||||||
#include "missile.h"
|
#include "missile.h"
|
||||||
#include "shadermanager.h"
|
#include "shadermanager.h"
|
||||||
|
|
||||||
|
#include <framework/graphics/graphics.h>
|
||||||
|
#include <framework/graphics/framebuffermanager.h>
|
||||||
#include <framework/core/eventdispatcher.h>
|
#include <framework/core/eventdispatcher.h>
|
||||||
|
#include <framework/application.h>
|
||||||
|
|
||||||
MapView::MapView()
|
MapView::MapView()
|
||||||
{
|
{
|
||||||
|
@ -41,12 +43,17 @@ MapView::MapView()
|
||||||
m_cachedLastVisibleFloor = 7;
|
m_cachedLastVisibleFloor = 7;
|
||||||
m_optimizedSize = Size(Otc::AWARE_X_TILES, Otc::AWARE_Y_TILES) * Otc::TILE_PIXELS;
|
m_optimizedSize = Size(Otc::AWARE_X_TILES, Otc::AWARE_Y_TILES) * Otc::TILE_PIXELS;
|
||||||
|
|
||||||
m_framebuffer = FrameBufferPtr(new FrameBuffer());
|
m_framebuffer = g_framebuffers.createFrameBuffer();
|
||||||
setVisibleDimension(Size(15, 11));
|
setVisibleDimension(Size(15, 11));
|
||||||
|
|
||||||
m_shader = g_shaders.getDefaultMapShader();
|
m_shader = g_shaders.getDefaultMapShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MapView::~MapView()
|
||||||
|
{
|
||||||
|
assert(!g_app->isTermianted());
|
||||||
|
}
|
||||||
|
|
||||||
void MapView::draw(const Rect& rect)
|
void MapView::draw(const Rect& rect)
|
||||||
{
|
{
|
||||||
// update visible tiles cache when needed
|
// update visible tiles cache when needed
|
||||||
|
|
|
@ -50,6 +50,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
MapView();
|
MapView();
|
||||||
|
~MapView();
|
||||||
void draw(const Rect& rect);
|
void draw(const Rect& rect);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -44,6 +44,7 @@ void ShaderManager::terminate()
|
||||||
{
|
{
|
||||||
m_defaultItemShader = nullptr;
|
m_defaultItemShader = nullptr;
|
||||||
m_defaultMapShader = nullptr;
|
m_defaultMapShader = nullptr;
|
||||||
|
m_shaders.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
PainterShaderProgramPtr ShaderManager::createShader(const std::string& name)
|
PainterShaderProgramPtr ShaderManager::createShader(const std::string& name)
|
||||||
|
|
|
@ -156,6 +156,4 @@ private:
|
||||||
friend class ThingsType;
|
friend class ThingsType;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::vector<ThingType> ThingTypeList;
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -117,5 +117,7 @@ void OTClient::init(const std::vector<std::string>& args)
|
||||||
void OTClient::terminate()
|
void OTClient::terminate()
|
||||||
{
|
{
|
||||||
g_shaders.terminate();
|
g_shaders.terminate();
|
||||||
|
g_map.clean();
|
||||||
|
g_thingsType.unload();
|
||||||
Application::terminate();
|
Application::terminate();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue