diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml
index f8b0f92..165e683 100644
--- a/android/src/main/AndroidManifest.xml
+++ b/android/src/main/AndroidManifest.xml
@@ -3,8 +3,10 @@
package="com.omigamedev"
android:versionCode="1"
android:versionName="1.0">
-
-
+
+
+ app->activity->assetManager;
+ App::I.data_path = engine->app->activity->externalDataPath;
App::I.width = w;
App::I.height = h;
App::I.init();
@@ -357,7 +358,6 @@ static void engine_term_display(struct engine* engine) {
engine->display = EGL_NO_DISPLAY;
engine->context = EGL_NO_CONTEXT;
engine->surface = EGL_NO_SURFACE;
- App::I.terminate();
}
/**
@@ -366,7 +366,7 @@ static void engine_term_display(struct engine* engine) {
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
struct engine* engine = (struct engine*)app->userData;
int32_t eventType = AInputEvent_getType(event);
- LOG("event type: %d", eventType);
+ //LOG("event type: %d", eventType);
switch (eventType) {
case AINPUT_EVENT_TYPE_MOTION:
// switch (AInputEvent_getSource(event)) {
@@ -384,7 +384,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
int ret = -1;
for (int i = 0; i < count; i++)
{
- LOG("pointer %d id %d == %d", i, id, AMotionEvent_getPointerId(event, i));
+ //LOG("pointer %d id %d == %d", i, id, AMotionEvent_getPointerId(event, i));
if (AMotionEvent_getPointerId(event, i) == id)
ret = i;
}
@@ -400,7 +400,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
static Pointer p0, p1;
static int tracked = 0;
//LOG("event source: %d", AInputEvent_getSource(event));
- LOG("pointer id %d count %d", pointer_id, count);
+ //LOG("pointer id %d count %d", pointer_id, count);
MouseEvent e;
switch (action) {
case AMOTION_EVENT_ACTION_DOWN:
@@ -412,12 +412,12 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
p0.idx = index;
App::I.mouse_down(0, x, y);
tracked = 1;
- LOG("first down");
+ //LOG("first down");
return 1;
}
case AMOTION_EVENT_ACTION_POINTER_DOWN:
{
- LOG("pointer down index %d", index);
+ //LOG("pointer down index %d", index);
if (count == 2)
{
float y = AMotionEvent_getY(event, 1);
@@ -426,7 +426,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
p1.idx = index;
p1.pos = {x, y};
tracked = 2;
- LOG("second down");
+ //LOG("second down");
App::I.mouse_cancel(0);
App::I.gesture_start(p0.pos, p1.pos);
}
@@ -440,14 +440,14 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
p0.id = -1;
p1.id = -1;
App::I.mouse_up(0, x, y);
- LOG("first up");
+ //LOG("first up");
return 1;
}
case AMOTION_EVENT_ACTION_POINTER_UP:
if (p1.id == AMotionEvent_getPointerId(event, 1))
{
p1.id = -1;
- LOG("second up");
+ //LOG("second up");
App::I.gesture_end();
}
return 1;
@@ -456,7 +456,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
float y = AMotionEvent_getY(event, 0);
float x = AMotionEvent_getX(event, 0);
App::I.mouse_move(x, y);
- LOG("single move");
+ //LOG("single move");
return 1;
}
case AMOTION_EVENT_ACTION_MOVE:
@@ -465,22 +465,22 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
float y = AMotionEvent_getY(event, 0);
float x = AMotionEvent_getX(event, 0);
App::I.mouse_move(x, y);
- LOG("single move");
+ //LOG("single move");
}
else if (count == 2)
{
int idx = findPointer(pointer_id, event);
- LOG("pointer move index %d", idx);
+ //LOG("pointer move index %d", idx);
if (p0.idx == idx)
{
- LOG("first move");
+ //LOG("first move");
float y = AMotionEvent_getY(event, 0);
float x = AMotionEvent_getX(event, 0);
p0.pos = {x, y};
}
if (p1.idx == idx)
{
- LOG("second move");
+ //LOG("second move");
float x = AMotionEvent_getX(event, 1);
float y = AMotionEvent_getY(event, 1);
p1.pos = {x, y};
@@ -528,6 +528,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
break;
case APP_CMD_TERM_WINDOW:
// The window is being hidden or closed, clean it up.
+ App::I.terminate();
engine_term_display(engine);
//exit(0);
break;
diff --git a/engine/app.cpp b/engine/app.cpp
index d87804d..3fa5bb8 100644
--- a/engine/app.cpp
+++ b/engine/app.cpp
@@ -298,6 +298,7 @@ void App::initLayout()
sidebar = layout[main_id]->find("sidebar");
panels = layout[main_id]->find("panels");
canvas = layout[main_id]->find("paint-canvas");
+ canvas->data_path = data_path;
//brushes = layout[main_id]->find("panel-brush");
//layers = layout[main_id]->find("panel-layer");
@@ -413,6 +414,7 @@ void App::initLayout()
//exit(0);
if (canvas)
{
+ canvas->m_canvas->snapshot_save(data_path);
canvas->m_canvas->m_use_instanced = !canvas->m_canvas->m_use_instanced;
//button->color_normal = canvas->m_canvas->m_use_instanced ? glm::vec4(1, 0, 0, 1) : glm::vec4(0, 1, 0, 1);
button->m_text->set_text(canvas->m_canvas->m_use_instanced ? "INST" : "NORM");
@@ -500,7 +502,14 @@ void App::initLayout()
};
LOG("initializing layout xml");
if (layout.m_loaded)
- layout[main_id]->restore_context();
+ {
+ LOG("restore layout");
+ layout.restore_context();
+ if (panels->get_child_index(brushes.get()) == -1) brushes->restore_context();
+ if (panels->get_child_index(layers.get()) == -1) layers->restore_context();
+ if (panels->get_child_index(color.get()) == -1) color->restore_context();
+ if (panels->get_child_index(stroke.get()) == -1) stroke->restore_context();
+ }
else
layout.load("data/layout.xml");
LOG("initializing layout completed");
@@ -722,5 +731,12 @@ bool App::key_char(char key)
void App::terminate()
{
+ LOG("App::terminate");
TextureManager::invalidate();
+ ShaderManager::invalidate();
+ layout.clear_context();
+ brushes->clear_context();
+ layers->clear_context();
+ color->clear_context();
+ stroke->clear_context();
}
diff --git a/engine/app.h b/engine/app.h
index 2a03ffd..332d910 100644
--- a/engine/app.h
+++ b/engine/app.h
@@ -11,6 +11,7 @@ class App
{
public:
static App I;
+ std::string data_path;
Sampler sampler;
Texture2D tex;
LayoutManager layout;
diff --git a/engine/canvas.cpp b/engine/canvas.cpp
index a5d17ba..0e1218a 100644
--- a/engine/canvas.cpp
+++ b/engine/canvas.cpp
@@ -362,15 +362,112 @@ bool ui::Canvas::create(int width, int height)
m_plane.create<1>(1, 1);
m_plane_brush.create<1>(1, 1);
m_mesh.create();
+ for (auto& l : m_layers)
+ {
+ l.create(width, height, "");
+ }
return true;
}
-void ui::Canvas::snapshot_save()
+void ui::Canvas::snapshot_save(std::string data_path)
{
-
+ LOG("SAVE SNAPSHOT");
+ m_layers_snapshot.clear();
+ m_layers_snapshot.resize(m_layers.size());
+ for (int i = 0; i < m_layers.size(); i++)
+ m_layers_snapshot[i] = m_layers[i].snapshot(data_path);
}
void ui::Canvas::snapshot_restore()
{
+ LOG("RESTORE SNAPSHOT");
+ for (int i = 0; i < m_layers.size(); i++)
+ m_layers[i].restore(m_layers_snapshot[i]);
+ m_layers_snapshot.clear();
+ LOG("RESTORE SNAPSHOT complete");
+}
-};
\ No newline at end of file
+void ui::Canvas::clear_context()
+{
+ LOG("Canvas CLEAR CONTEXT");
+ for (auto& layer : m_layers)
+ layer.destroy();
+ for (int i = 0; i < 6; i++)
+ {
+ m_tmp[i].destroy();
+ m_tex[i].destroy();
+ m_tex2[i].destroy();
+ }
+};
+
+///////////////////////////////////////////////////////////////////////////////////////////
+
+void ui::Layer::destroy()
+{
+ for (int i = 0; i < 6; i++)
+ m_rtt[i].destroy();
+}
+
+void ui::Layer::restore(const Snapshot& snap)
+{
+ for (int i = 0; i < 6; i++)
+ {
+ if (!snap.image[i])
+ continue;
+ m_rtt[i].create(512, 512); // TODO: this should not be recreated here! Sorry I messed up with this, just quick fix DON'T SHIP!!
+ m_rtt[i].bindTexture();
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, m_rtt[i].getWidth(), m_rtt[i].getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, snap.image[i].get());
+ m_rtt[i].unbindTexture();
+ LOG("restore face %d - %d bytes (%dx%d)", i, m_rtt[i].bytes(), m_rtt[i].getWidth(), m_rtt[i].getHeight());
+ }
+}
+
+ui::Layer::Snapshot ui::Layer::snapshot(std::string data_path)
+{
+ Snapshot snap;
+ static int counter = 0;
+ LOG("errno = %d", errno);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ for (int i = 0; i < 6; i++)
+ {
+ snap.image[i] = std::make_unique(m_rtt[i].bytes());
+ m_rtt[i].readTextureData(snap.image[i].get());
+ LOG("snapshot face %d - %d bytes (%dx%d)", i, m_rtt[i].bytes(), m_rtt[i].getWidth(), m_rtt[i].getHeight());
+ static char name[128];
+ sprintf(name, "%s/Layer%d-%d.png", data_path.c_str(), counter, i);
+ //int ret = stbi_write_png(name, m_rtt[i].getWidth(), m_rtt[i].getHeight(), 4, snap.image[i].get(), m_rtt[i].stride());
+ }
+ counter++;
+ return std::move(snap);
+}
+
+void ui::Layer::clear(const glm::vec4& c)
+{
+ // push clear color state
+ GLfloat cc[4];
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
+ glClearColor(c.r, c.g, c.b, c.a);
+
+ for (int i = 0; i < 6; i++)
+ {
+ m_rtt[i].bindFramebuffer();
+ glClear(GL_COLOR_BUFFER_BIT);
+ m_rtt[i].unbindFramebuffer();
+ }
+
+ // restore clear color state
+ glClearColor(cc[0], cc[1], cc[2], cc[3]);
+}
+
+bool ui::Layer::create(int width, int height, std::string name)
+{
+ for (int i = 0; i < 6; i++)
+ {
+ m_rtt[i].create(width, height);
+ m_rtt[i].bindFramebuffer();
+ m_rtt[i].clear();
+ m_rtt[i].unbindFramebuffer();
+ }
+ return true;
+}
diff --git a/engine/canvas.h b/engine/canvas.h
index 97811c0..b06d962 100644
--- a/engine/canvas.h
+++ b/engine/canvas.h
@@ -20,44 +20,11 @@ public:
{
std::unique_ptr image[6];
};
- bool create(int width, int height, std::string name)
- {
- for (int i = 0; i < 6; i++)
- {
- m_rtt[i].create(width, height);
- m_rtt[i].bindFramebuffer();
- m_rtt[i].clear();
- m_rtt[i].unbindFramebuffer();
- }
- return true;
- }
- void clear(const glm::vec4& c)
- {
- // push clear color state
- GLfloat cc[4];
- glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
- glClearColor(c.r, c.g, c.b, c.a);
-
- for (int i = 0; i < 6; i++)
- {
- m_rtt[i].bindFramebuffer();
- glClear(GL_COLOR_BUFFER_BIT);
- m_rtt[i].unbindFramebuffer();
- }
-
- // restore clear color state
- glClearColor(cc[0], cc[1], cc[2], cc[3]);
- }
- Snapshot snapshot()
- {
- Snapshot snap;
- for (int i = 0; i < 6; i++)
- {
- snap.image[i] = std::make_unique(m_rtt[i].bytes());
- m_rtt[i].readTextureData(snap.image[i].get());
- }
- return snap;
- }
+ bool create(int width, int height, std::string name);
+ void clear(const glm::vec4& c);
+ Snapshot snapshot(std::string data_path);
+ void restore(const Snapshot& snap);
+ void destroy();
};
class Canvas
@@ -105,8 +72,9 @@ public:
void stroke_end();
void stroke_commit();
void clear(const glm::vec4& color = { 1, 1, 1, 1 });
- void snapshot_save();
+ void snapshot_save(std::string data_path);
void snapshot_restore();
+ void clear_context();
};
diff --git a/engine/font.h b/engine/font.h
index 23f5855..eaccdb6 100644
--- a/engine/font.h
+++ b/engine/font.h
@@ -31,6 +31,7 @@ public:
static void init();
static bool load(kFont id, const char* ttf, int sz);
static const Font& get(kFont id);
+ static void invalidate() { m_fonts.clear(); }
};
class TextMesh
diff --git a/engine/layout.cpp b/engine/layout.cpp
index 9bb13cf..c054c2e 100644
--- a/engine/layout.cpp
+++ b/engine/layout.cpp
@@ -612,3 +612,15 @@ bool LayoutManager::reload()
std::string path_copy = m_path;
return load(path_copy.c_str());
}
+
+void LayoutManager::restore_context()
+{
+ for (auto& node : m_layouts)
+ node.second->restore_context();
+}
+
+void LayoutManager::clear_context()
+{
+ for (auto& node : m_layouts)
+ node.second->clear_context();
+}
diff --git a/engine/layout.h b/engine/layout.h
index 0b150f8..098168e 100644
--- a/engine/layout.h
+++ b/engine/layout.h
@@ -101,6 +101,8 @@ public:
auto i = m_layouts.find(id);
return i == m_layouts.end() ? nullptr : i->second.get();
}
+ void restore_context();
+ void clear_context();
//Node& operator[](const char* ids) { return m_layouts[const_hash(ids)]; }
};
@@ -222,10 +224,13 @@ public:
virtual void restore_context()
{
for (auto& c : m_children)
- {
c->restore_context();
- }
};
+ virtual void clear_context()
+ {
+ for (auto& c : m_children)
+ c->clear_context();
+ }
void update(float width, float height, float zoom);
void update();
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
@@ -482,6 +487,7 @@ public:
{
if (!m_path.empty() && TextureManager::load(m_path.c_str()))
{
+ //LOG("load image node %s", m_path.c_str());
auto tex_sz = TextureManager::get(m_tex_id).size();
m_off = m_region.xy / tex_sz;
m_sz = (m_region.zw - m_region.xy) / tex_sz;
@@ -885,6 +891,7 @@ public:
i += strlen(s) + 1;
}
file.close();
+ TextureManager::load("data/spritesheet.png");
}
virtual Node* clone_instantiate() const override { return new NodeIcon(); }
virtual void clone_copy(Node* dest) const override
@@ -1700,7 +1707,13 @@ public:
{
NodeBorder::restore_context();
init_controls();
- m_rtt.create(m_rtt.getWidth(), m_rtt.getHeight());
+ if (m_size.x > 0 && m_size.y > 0)
+ m_rtt.create(m_size.x, m_size.y);
+ }
+ virtual void clear_context() override
+ {
+ NodeBorder::clear_context();
+ m_rtt.destroy();
}
void draw_stroke()
{
@@ -1856,6 +1869,7 @@ class NodeCanvas : public Node
float m_zoom_start;
bool method = true;
public:
+ std::string data_path;
std::unique_ptr m_canvas;
ui::Brush m_brush;
Sampler m_sampler;
@@ -1876,7 +1890,15 @@ public:
Node::restore_context();
m_canvas->create(512, 512);
m_sampler.create();
+ //m_canvas->clear();
m_face_plane.create<1>(2, 2);
+ m_canvas->snapshot_restore();
+ }
+ virtual void clear_context() override
+ {
+ Node::clear_context();
+ m_canvas->snapshot_save(data_path);
+ m_canvas->clear_context();
}
virtual void draw() override
{
diff --git a/engine/pch.cpp b/engine/pch.cpp
index 53b0580..21cf628 100644
--- a/engine/pch.cpp
+++ b/engine/pch.cpp
@@ -6,6 +6,9 @@
#define STB_IMAGE_IMPLEMENTATION
#include
+#define STB_IMAGE_WRITE_IMPLEMENTATION
+#include
+
#ifdef DEBUG
#pragma comment (lib, "libcurl_debug.lib")
#else
diff --git a/engine/pch.h b/engine/pch.h
index 7215e66..e8d2cd4 100644
--- a/engine/pch.h
+++ b/engine/pch.h
@@ -73,4 +73,5 @@
#include
#include
#include
+#include
#include
diff --git a/engine/rtt.cpp b/engine/rtt.cpp
index 18ed8bb..e998aa5 100644
--- a/engine/rtt.cpp
+++ b/engine/rtt.cpp
@@ -30,11 +30,12 @@ void RTT::destroy()
{
unbindFramebuffer();
glDeleteFramebuffers(1, &fboID);
+ LOG("RTT DESTROY %d", fboID);
}
fboID = 0;
rboID = 0;
- w = 0;
- h = 0;
+// w = 0;
+// h = 0;
}
bool RTT::create(int width, int height, int tex/* = -1*/)
@@ -74,6 +75,7 @@ bool RTT::create(int width, int height, int tex/* = -1*/)
// Create a framebuffer object
glGenFramebuffers(1, &fboID);
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
+ LOG("RTT CREATE %d - tex %d", fboID, texID);
// Attach the texture to FBO color attachment point
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
@@ -136,10 +138,12 @@ void RTT::clear(glm::vec4 color)
void RTT::readTextureData(uint8_t* buffer)
{
- bindTexture();
+ glReadBuffer(GL_BACK);
+ bindFramebuffer();
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
- glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer);
- unbindTexture();
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
+ unbindFramebuffer();
+ glReadBuffer(GL_NONE);
}
uint8_t* RTT::createBuffer()
diff --git a/engine/rtt.h b/engine/rtt.h
index 9d9a869..1074cb8 100644
--- a/engine/rtt.h
+++ b/engine/rtt.h
@@ -27,5 +27,6 @@ public:
int getWidth() { return w; }
int getHeight() { return h; }
int bytes() { return w * h * 4; }
+ int stride() { return w * 4; }
GLuint getFBO() { return fboID; }
};
diff --git a/engine/shader.cpp b/engine/shader.cpp
index 3db4ae6..426e3d1 100644
--- a/engine/shader.cpp
+++ b/engine/shader.cpp
@@ -169,4 +169,9 @@ void ShaderManager::u_int(kShaderUniform id, int i)
void ui::ShaderManager::u_float(kShaderUniform id, float f)
{
m_current->u_float(id, f);
-}
\ No newline at end of file
+}
+
+void ShaderManager::invalidate()
+{
+ m_shaders.clear();
+}
diff --git a/engine/shader.h b/engine/shader.h
index a6cf823..f603566 100644
--- a/engine/shader.h
+++ b/engine/shader.h
@@ -60,6 +60,7 @@ public:
static void u_mat4(kShaderUniform id, const glm::mat4& m);
static void u_int(kShaderUniform id, int i);
static void u_float(kShaderUniform id, float f);
+ static void invalidate();
};
}
\ No newline at end of file
diff --git a/engine/texture.cpp b/engine/texture.cpp
index ba5e6df..29694b2 100644
--- a/engine/texture.cpp
+++ b/engine/texture.cpp
@@ -27,6 +27,10 @@ Texture2D& TextureManager::get(uint16_t id)
void TextureManager::invalidate()
{
+ for (auto& t : m_textures)
+ {
+ t.second.destroy();
+ }
m_textures.clear();
}
@@ -37,6 +41,7 @@ bool Texture2D::create(int width, int height, GLint internal_format, GLint forma
m_format = format;
m_iformat = internal_format;
glGenTextures(1, &m_tex);
+ LOG("genTex %d", m_tex);
bind();
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
unbind();
@@ -60,6 +65,7 @@ void Texture2D::assign(GLuint tex, int w/* = -1*/, int h/* = -1*/, GLuint intern
bool Texture2D::load(std::string filename)
{
+ LOG("load texture %s", filename.c_str());
ui::Image img;
if (!img.load(filename))
return false;
diff --git a/engine/texture.h b/engine/texture.h
index df789cc..880fe26 100644
--- a/engine/texture.h
+++ b/engine/texture.h
@@ -13,7 +13,7 @@ public:
bool create(const ui::Image& img);
void assign(GLuint tex, int w = -1, int h = -1, GLuint internal_format = GL_RGBA8, GLuint format = GL_RGBA);
bool load(std::string filename);
- void destroy() { glDeleteTextures(1, &m_tex); }
+ void destroy() { LOG("TEX destroy %d", m_tex); glDeleteTextures(1, &m_tex); }
void bind() const { glBindTexture(GL_TEXTURE_2D, m_tex); }
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
void update(const uint8_t* data);