save and restore layers image when context is lost in Android
This commit is contained in:
@@ -4,6 +4,8 @@
|
|||||||
android:versionCode="1"
|
android:versionCode="1"
|
||||||
android:versionName="1.0">
|
android:versionName="1.0">
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||||
<application android:label="@string/app_name"
|
<application android:label="@string/app_name"
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_launcher"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
|
|||||||
@@ -313,6 +313,7 @@ static int engine_init_display(struct engine* engine) {
|
|||||||
glDisable(GL_DEPTH_TEST);
|
glDisable(GL_DEPTH_TEST);
|
||||||
//glEnableClientState(GL_VERTEX_ARRAY);
|
//glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
Asset::m_am = engine->app->activity->assetManager;
|
Asset::m_am = engine->app->activity->assetManager;
|
||||||
|
App::I.data_path = engine->app->activity->externalDataPath;
|
||||||
App::I.width = w;
|
App::I.width = w;
|
||||||
App::I.height = h;
|
App::I.height = h;
|
||||||
App::I.init();
|
App::I.init();
|
||||||
@@ -357,7 +358,6 @@ static void engine_term_display(struct engine* engine) {
|
|||||||
engine->display = EGL_NO_DISPLAY;
|
engine->display = EGL_NO_DISPLAY;
|
||||||
engine->context = EGL_NO_CONTEXT;
|
engine->context = EGL_NO_CONTEXT;
|
||||||
engine->surface = EGL_NO_SURFACE;
|
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) {
|
static int32_t engine_handle_input(struct android_app* app, AInputEvent* event) {
|
||||||
struct engine* engine = (struct engine*)app->userData;
|
struct engine* engine = (struct engine*)app->userData;
|
||||||
int32_t eventType = AInputEvent_getType(event);
|
int32_t eventType = AInputEvent_getType(event);
|
||||||
LOG("event type: %d", eventType);
|
//LOG("event type: %d", eventType);
|
||||||
switch (eventType) {
|
switch (eventType) {
|
||||||
case AINPUT_EVENT_TYPE_MOTION:
|
case AINPUT_EVENT_TYPE_MOTION:
|
||||||
// switch (AInputEvent_getSource(event)) {
|
// switch (AInputEvent_getSource(event)) {
|
||||||
@@ -384,7 +384,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
|
|||||||
int ret = -1;
|
int ret = -1;
|
||||||
for (int i = 0; i < count; i++)
|
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)
|
if (AMotionEvent_getPointerId(event, i) == id)
|
||||||
ret = i;
|
ret = i;
|
||||||
}
|
}
|
||||||
@@ -400,7 +400,7 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
|
|||||||
static Pointer p0, p1;
|
static Pointer p0, p1;
|
||||||
static int tracked = 0;
|
static int tracked = 0;
|
||||||
//LOG("event source: %d", AInputEvent_getSource(event));
|
//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;
|
MouseEvent e;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case AMOTION_EVENT_ACTION_DOWN:
|
case AMOTION_EVENT_ACTION_DOWN:
|
||||||
@@ -412,12 +412,12 @@ static int32_t engine_handle_input(struct android_app* app, AInputEvent* event)
|
|||||||
p0.idx = index;
|
p0.idx = index;
|
||||||
App::I.mouse_down(0, x, y);
|
App::I.mouse_down(0, x, y);
|
||||||
tracked = 1;
|
tracked = 1;
|
||||||
LOG("first down");
|
//LOG("first down");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
case AMOTION_EVENT_ACTION_POINTER_DOWN:
|
||||||
{
|
{
|
||||||
LOG("pointer down index %d", index);
|
//LOG("pointer down index %d", index);
|
||||||
if (count == 2)
|
if (count == 2)
|
||||||
{
|
{
|
||||||
float y = AMotionEvent_getY(event, 1);
|
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.idx = index;
|
||||||
p1.pos = {x, y};
|
p1.pos = {x, y};
|
||||||
tracked = 2;
|
tracked = 2;
|
||||||
LOG("second down");
|
//LOG("second down");
|
||||||
App::I.mouse_cancel(0);
|
App::I.mouse_cancel(0);
|
||||||
App::I.gesture_start(p0.pos, p1.pos);
|
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;
|
p0.id = -1;
|
||||||
p1.id = -1;
|
p1.id = -1;
|
||||||
App::I.mouse_up(0, x, y);
|
App::I.mouse_up(0, x, y);
|
||||||
LOG("first up");
|
//LOG("first up");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case AMOTION_EVENT_ACTION_POINTER_UP:
|
case AMOTION_EVENT_ACTION_POINTER_UP:
|
||||||
if (p1.id == AMotionEvent_getPointerId(event, 1))
|
if (p1.id == AMotionEvent_getPointerId(event, 1))
|
||||||
{
|
{
|
||||||
p1.id = -1;
|
p1.id = -1;
|
||||||
LOG("second up");
|
//LOG("second up");
|
||||||
App::I.gesture_end();
|
App::I.gesture_end();
|
||||||
}
|
}
|
||||||
return 1;
|
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 y = AMotionEvent_getY(event, 0);
|
||||||
float x = AMotionEvent_getX(event, 0);
|
float x = AMotionEvent_getX(event, 0);
|
||||||
App::I.mouse_move(x, y);
|
App::I.mouse_move(x, y);
|
||||||
LOG("single move");
|
//LOG("single move");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
case AMOTION_EVENT_ACTION_MOVE:
|
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 y = AMotionEvent_getY(event, 0);
|
||||||
float x = AMotionEvent_getX(event, 0);
|
float x = AMotionEvent_getX(event, 0);
|
||||||
App::I.mouse_move(x, y);
|
App::I.mouse_move(x, y);
|
||||||
LOG("single move");
|
//LOG("single move");
|
||||||
}
|
}
|
||||||
else if (count == 2)
|
else if (count == 2)
|
||||||
{
|
{
|
||||||
int idx = findPointer(pointer_id, event);
|
int idx = findPointer(pointer_id, event);
|
||||||
LOG("pointer move index %d", idx);
|
//LOG("pointer move index %d", idx);
|
||||||
if (p0.idx == idx)
|
if (p0.idx == idx)
|
||||||
{
|
{
|
||||||
LOG("first move");
|
//LOG("first move");
|
||||||
float y = AMotionEvent_getY(event, 0);
|
float y = AMotionEvent_getY(event, 0);
|
||||||
float x = AMotionEvent_getX(event, 0);
|
float x = AMotionEvent_getX(event, 0);
|
||||||
p0.pos = {x, y};
|
p0.pos = {x, y};
|
||||||
}
|
}
|
||||||
if (p1.idx == idx)
|
if (p1.idx == idx)
|
||||||
{
|
{
|
||||||
LOG("second move");
|
//LOG("second move");
|
||||||
float x = AMotionEvent_getX(event, 1);
|
float x = AMotionEvent_getX(event, 1);
|
||||||
float y = AMotionEvent_getY(event, 1);
|
float y = AMotionEvent_getY(event, 1);
|
||||||
p1.pos = {x, y};
|
p1.pos = {x, y};
|
||||||
@@ -528,6 +528,7 @@ static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
|
|||||||
break;
|
break;
|
||||||
case APP_CMD_TERM_WINDOW:
|
case APP_CMD_TERM_WINDOW:
|
||||||
// The window is being hidden or closed, clean it up.
|
// The window is being hidden or closed, clean it up.
|
||||||
|
App::I.terminate();
|
||||||
engine_term_display(engine);
|
engine_term_display(engine);
|
||||||
//exit(0);
|
//exit(0);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -298,6 +298,7 @@ void App::initLayout()
|
|||||||
sidebar = layout[main_id]->find<NodeBorder>("sidebar");
|
sidebar = layout[main_id]->find<NodeBorder>("sidebar");
|
||||||
panels = layout[main_id]->find<Node>("panels");
|
panels = layout[main_id]->find<Node>("panels");
|
||||||
canvas = layout[main_id]->find<NodeCanvas>("paint-canvas");
|
canvas = layout[main_id]->find<NodeCanvas>("paint-canvas");
|
||||||
|
canvas->data_path = data_path;
|
||||||
|
|
||||||
//brushes = layout[main_id]->find<NodePanelBrush>("panel-brush");
|
//brushes = layout[main_id]->find<NodePanelBrush>("panel-brush");
|
||||||
//layers = layout[main_id]->find<NodePanelLayer>("panel-layer");
|
//layers = layout[main_id]->find<NodePanelLayer>("panel-layer");
|
||||||
@@ -413,6 +414,7 @@ void App::initLayout()
|
|||||||
//exit(0);
|
//exit(0);
|
||||||
if (canvas)
|
if (canvas)
|
||||||
{
|
{
|
||||||
|
canvas->m_canvas->snapshot_save(data_path);
|
||||||
canvas->m_canvas->m_use_instanced = !canvas->m_canvas->m_use_instanced;
|
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->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");
|
button->m_text->set_text(canvas->m_canvas->m_use_instanced ? "INST" : "NORM");
|
||||||
@@ -500,7 +502,14 @@ void App::initLayout()
|
|||||||
};
|
};
|
||||||
LOG("initializing layout xml");
|
LOG("initializing layout xml");
|
||||||
if (layout.m_loaded)
|
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
|
else
|
||||||
layout.load("data/layout.xml");
|
layout.load("data/layout.xml");
|
||||||
LOG("initializing layout completed");
|
LOG("initializing layout completed");
|
||||||
@@ -722,5 +731,12 @@ bool App::key_char(char key)
|
|||||||
|
|
||||||
void App::terminate()
|
void App::terminate()
|
||||||
{
|
{
|
||||||
|
LOG("App::terminate");
|
||||||
TextureManager::invalidate();
|
TextureManager::invalidate();
|
||||||
|
ShaderManager::invalidate();
|
||||||
|
layout.clear_context();
|
||||||
|
brushes->clear_context();
|
||||||
|
layers->clear_context();
|
||||||
|
color->clear_context();
|
||||||
|
stroke->clear_context();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ class App
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static App I;
|
static App I;
|
||||||
|
std::string data_path;
|
||||||
Sampler sampler;
|
Sampler sampler;
|
||||||
Texture2D tex;
|
Texture2D tex;
|
||||||
LayoutManager layout;
|
LayoutManager layout;
|
||||||
|
|||||||
@@ -362,15 +362,112 @@ bool ui::Canvas::create(int width, int height)
|
|||||||
m_plane.create<1>(1, 1);
|
m_plane.create<1>(1, 1);
|
||||||
m_plane_brush.create<1>(1, 1);
|
m_plane_brush.create<1>(1, 1);
|
||||||
m_mesh.create();
|
m_mesh.create();
|
||||||
|
for (auto& l : m_layers)
|
||||||
|
{
|
||||||
|
l.create(width, height, "");
|
||||||
|
}
|
||||||
return true;
|
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()
|
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");
|
||||||
|
}
|
||||||
|
|
||||||
|
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<uint8_t[]>(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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -20,44 +20,11 @@ public:
|
|||||||
{
|
{
|
||||||
std::unique_ptr<uint8_t[]> image[6];
|
std::unique_ptr<uint8_t[]> image[6];
|
||||||
};
|
};
|
||||||
bool create(int width, int height, std::string name)
|
bool create(int width, int height, std::string name);
|
||||||
{
|
void clear(const glm::vec4& c);
|
||||||
for (int i = 0; i < 6; i++)
|
Snapshot snapshot(std::string data_path);
|
||||||
{
|
void restore(const Snapshot& snap);
|
||||||
m_rtt[i].create(width, height);
|
void destroy();
|
||||||
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<uint8_t[]>(m_rtt[i].bytes());
|
|
||||||
m_rtt[i].readTextureData(snap.image[i].get());
|
|
||||||
}
|
|
||||||
return snap;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Canvas
|
class Canvas
|
||||||
@@ -105,8 +72,9 @@ public:
|
|||||||
void stroke_end();
|
void stroke_end();
|
||||||
void stroke_commit();
|
void stroke_commit();
|
||||||
void clear(const glm::vec4& color = { 1, 1, 1, 1 });
|
void clear(const glm::vec4& color = { 1, 1, 1, 1 });
|
||||||
void snapshot_save();
|
void snapshot_save(std::string data_path);
|
||||||
void snapshot_restore();
|
void snapshot_restore();
|
||||||
|
void clear_context();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ public:
|
|||||||
static void init();
|
static void init();
|
||||||
static bool load(kFont id, const char* ttf, int sz);
|
static bool load(kFont id, const char* ttf, int sz);
|
||||||
static const Font& get(kFont id);
|
static const Font& get(kFont id);
|
||||||
|
static void invalidate() { m_fonts.clear(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
class TextMesh
|
class TextMesh
|
||||||
|
|||||||
@@ -612,3 +612,15 @@ bool LayoutManager::reload()
|
|||||||
std::string path_copy = m_path;
|
std::string path_copy = m_path;
|
||||||
return load(path_copy.c_str());
|
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();
|
||||||
|
}
|
||||||
|
|||||||
@@ -101,6 +101,8 @@ public:
|
|||||||
auto i = m_layouts.find(id);
|
auto i = m_layouts.find(id);
|
||||||
return i == m_layouts.end() ? nullptr : i->second.get();
|
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)]; }
|
//Node& operator[](const char* ids) { return m_layouts[const_hash(ids)]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -222,10 +224,13 @@ public:
|
|||||||
virtual void restore_context()
|
virtual void restore_context()
|
||||||
{
|
{
|
||||||
for (auto& c : m_children)
|
for (auto& c : m_children)
|
||||||
{
|
|
||||||
c->restore_context();
|
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(float width, float height, float zoom);
|
||||||
void update();
|
void update();
|
||||||
void update_internal(const glm::vec2& origin, const glm::mat4& proj);
|
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()))
|
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();
|
auto tex_sz = TextureManager::get(m_tex_id).size();
|
||||||
m_off = m_region.xy / tex_sz;
|
m_off = m_region.xy / tex_sz;
|
||||||
m_sz = (m_region.zw - m_region.xy) / tex_sz;
|
m_sz = (m_region.zw - m_region.xy) / tex_sz;
|
||||||
@@ -885,6 +891,7 @@ public:
|
|||||||
i += strlen(s) + 1;
|
i += strlen(s) + 1;
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
TextureManager::load("data/spritesheet.png");
|
||||||
}
|
}
|
||||||
virtual Node* clone_instantiate() const override { return new NodeIcon(); }
|
virtual Node* clone_instantiate() const override { return new NodeIcon(); }
|
||||||
virtual void clone_copy(Node* dest) const override
|
virtual void clone_copy(Node* dest) const override
|
||||||
@@ -1700,7 +1707,13 @@ public:
|
|||||||
{
|
{
|
||||||
NodeBorder::restore_context();
|
NodeBorder::restore_context();
|
||||||
init_controls();
|
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()
|
void draw_stroke()
|
||||||
{
|
{
|
||||||
@@ -1856,6 +1869,7 @@ class NodeCanvas : public Node
|
|||||||
float m_zoom_start;
|
float m_zoom_start;
|
||||||
bool method = true;
|
bool method = true;
|
||||||
public:
|
public:
|
||||||
|
std::string data_path;
|
||||||
std::unique_ptr<ui::Canvas> m_canvas;
|
std::unique_ptr<ui::Canvas> m_canvas;
|
||||||
ui::Brush m_brush;
|
ui::Brush m_brush;
|
||||||
Sampler m_sampler;
|
Sampler m_sampler;
|
||||||
@@ -1876,7 +1890,15 @@ public:
|
|||||||
Node::restore_context();
|
Node::restore_context();
|
||||||
m_canvas->create(512, 512);
|
m_canvas->create(512, 512);
|
||||||
m_sampler.create();
|
m_sampler.create();
|
||||||
|
//m_canvas->clear();
|
||||||
m_face_plane.create<1>(2, 2);
|
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
|
virtual void draw() override
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
#define STB_IMAGE_IMPLEMENTATION
|
#define STB_IMAGE_IMPLEMENTATION
|
||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
|
|
||||||
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||||
|
#include <stb/stb_image_write.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#pragma comment (lib, "libcurl_debug.lib")
|
#pragma comment (lib, "libcurl_debug.lib")
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -73,4 +73,5 @@
|
|||||||
#include <yoga/Yoga.h>
|
#include <yoga/Yoga.h>
|
||||||
#include <stb/stb_truetype.h>
|
#include <stb/stb_truetype.h>
|
||||||
#include <stb/stb_image.h>
|
#include <stb/stb_image.h>
|
||||||
|
#include <stb/stb_image_write.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|||||||
@@ -30,11 +30,12 @@ void RTT::destroy()
|
|||||||
{
|
{
|
||||||
unbindFramebuffer();
|
unbindFramebuffer();
|
||||||
glDeleteFramebuffers(1, &fboID);
|
glDeleteFramebuffers(1, &fboID);
|
||||||
|
LOG("RTT DESTROY %d", fboID);
|
||||||
}
|
}
|
||||||
fboID = 0;
|
fboID = 0;
|
||||||
rboID = 0;
|
rboID = 0;
|
||||||
w = 0;
|
// w = 0;
|
||||||
h = 0;
|
// h = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTT::create(int width, int height, int tex/* = -1*/)
|
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
|
// Create a framebuffer object
|
||||||
glGenFramebuffers(1, &fboID);
|
glGenFramebuffers(1, &fboID);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
|
glBindFramebuffer(GL_FRAMEBUFFER, fboID);
|
||||||
|
LOG("RTT CREATE %d - tex %d", fboID, texID);
|
||||||
|
|
||||||
// Attach the texture to FBO color attachment point
|
// Attach the texture to FBO color attachment point
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texID, 0);
|
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)
|
void RTT::readTextureData(uint8_t* buffer)
|
||||||
{
|
{
|
||||||
bindTexture();
|
glReadBuffer(GL_BACK);
|
||||||
|
bindFramebuffer();
|
||||||
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
//glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
||||||
glReadPixels(0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, buffer);
|
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
|
||||||
unbindTexture();
|
unbindFramebuffer();
|
||||||
|
glReadBuffer(GL_NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* RTT::createBuffer()
|
uint8_t* RTT::createBuffer()
|
||||||
|
|||||||
@@ -27,5 +27,6 @@ public:
|
|||||||
int getWidth() { return w; }
|
int getWidth() { return w; }
|
||||||
int getHeight() { return h; }
|
int getHeight() { return h; }
|
||||||
int bytes() { return w * h * 4; }
|
int bytes() { return w * h * 4; }
|
||||||
|
int stride() { return w * 4; }
|
||||||
GLuint getFBO() { return fboID; }
|
GLuint getFBO() { return fboID; }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -170,3 +170,8 @@ void ui::ShaderManager::u_float(kShaderUniform id, float f)
|
|||||||
{
|
{
|
||||||
m_current->u_float(id, f);
|
m_current->u_float(id, f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ShaderManager::invalidate()
|
||||||
|
{
|
||||||
|
m_shaders.clear();
|
||||||
|
}
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public:
|
|||||||
static void u_mat4(kShaderUniform id, const glm::mat4& m);
|
static void u_mat4(kShaderUniform id, const glm::mat4& m);
|
||||||
static void u_int(kShaderUniform id, int i);
|
static void u_int(kShaderUniform id, int i);
|
||||||
static void u_float(kShaderUniform id, float f);
|
static void u_float(kShaderUniform id, float f);
|
||||||
|
static void invalidate();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -27,6 +27,10 @@ Texture2D& TextureManager::get(uint16_t id)
|
|||||||
|
|
||||||
void TextureManager::invalidate()
|
void TextureManager::invalidate()
|
||||||
{
|
{
|
||||||
|
for (auto& t : m_textures)
|
||||||
|
{
|
||||||
|
t.second.destroy();
|
||||||
|
}
|
||||||
m_textures.clear();
|
m_textures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,6 +41,7 @@ bool Texture2D::create(int width, int height, GLint internal_format, GLint forma
|
|||||||
m_format = format;
|
m_format = format;
|
||||||
m_iformat = internal_format;
|
m_iformat = internal_format;
|
||||||
glGenTextures(1, &m_tex);
|
glGenTextures(1, &m_tex);
|
||||||
|
LOG("genTex %d", m_tex);
|
||||||
bind();
|
bind();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
|
||||||
unbind();
|
unbind();
|
||||||
@@ -60,6 +65,7 @@ void Texture2D::assign(GLuint tex, int w/* = -1*/, int h/* = -1*/, GLuint intern
|
|||||||
|
|
||||||
bool Texture2D::load(std::string filename)
|
bool Texture2D::load(std::string filename)
|
||||||
{
|
{
|
||||||
|
LOG("load texture %s", filename.c_str());
|
||||||
ui::Image img;
|
ui::Image img;
|
||||||
if (!img.load(filename))
|
if (!img.load(filename))
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public:
|
|||||||
bool create(const ui::Image& img);
|
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);
|
void assign(GLuint tex, int w = -1, int h = -1, GLuint internal_format = GL_RGBA8, GLuint format = GL_RGBA);
|
||||||
bool load(std::string filename);
|
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 bind() const { glBindTexture(GL_TEXTURE_2D, m_tex); }
|
||||||
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
|
void unbind() const { glBindTexture(GL_TEXTURE_2D, 0); }
|
||||||
void update(const uint8_t* data);
|
void update(const uint8_t* data);
|
||||||
|
|||||||
Reference in New Issue
Block a user