added timeline slider and export animation frames

This commit is contained in:
2017-05-15 00:43:37 +01:00
parent 95509956f3
commit 7b99f0510a
10 changed files with 132 additions and 12 deletions

View File

@@ -393,6 +393,12 @@
<!--<panel-color id="panel-color"/>--> <!--<panel-color id="panel-color"/>-->
</scroll> </scroll>
</node> </node>
<!-- timeline -->
<node height="100%" width="1" grow="1" dir="col" justify="flex-end">
<border color=".3 .3 .3 .4" height="50" width="100%" pad="10">
<slider-h id="frames-slider"></slider-h>
</border>
</node>
</node> </node>
<!-- status bar --> <!-- status bar -->
<!--<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center"> <!--<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">

View File

@@ -47,7 +47,6 @@ bool App::mouse_scroll(float x, float y, float delta)
e.m_scroll_delta = delta * 0.1f; e.m_scroll_delta = delta * 0.1f;
auto ret = layout[main_id]->on_event(&e); auto ret = layout[main_id]->on_event(&e);
layout[main_id]->update(); layout[main_id]->update();
LOG("wheel x %.2f y %.2f", x, y);
return ret == kEventResult::Consumed; return ret == kEventResult::Consumed;
} }
bool App::mouse_cancel(int button) bool App::mouse_cancel(int button)

View File

@@ -232,7 +232,7 @@ void App::initLayout()
button->on_click = [this,button](Node*) { button->on_click = [this,button](Node*) {
if (canvas) if (canvas)
{ {
//canvas->m_canvas->export_anim(data_path); canvas->m_canvas->export_anim(data_path);
} }
}; };
} }
@@ -368,6 +368,29 @@ void App::initLayout()
{ {
toolbar->m_flood_events = true; toolbar->m_flood_events = true;
} }
if (auto* slider = layout[main_id]->find<NodeSliderH>("frames-slider"))
{
slider->on_value_changed = [this](Node*, float value)
{
auto& c = *ui::Canvas::I;
for (int i = 0; i < c.m_layers.size(); i++)
{
auto l = layers->get_layer_at(i);
layers->handle_layer_opacity(l, .0f);
}
int current_layer = (int)floor(value * c.m_layers.size());
auto l = layers->get_layer_at(current_layer);
layers->handle_layer_selected(l);
layers->handle_layer_opacity(l, 1.f);
if (current_layer > 0)
{
auto l = layers->get_layer_at(current_layer - 1);
layers->handle_layer_opacity(l, .25f);
}
};
}
}; };
LOG("initializing layout xml"); LOG("initializing layout xml");
if (layout.m_loaded) if (layout.m_loaded)

View File

@@ -451,7 +451,6 @@ void ui::Canvas::resize(int width, int height)
{ {
l.create(width, height, ""); l.create(width, height, "");
} }
m_latlong.create(width * 4, height * 2); // NOTE: w and h must be equal to make sense
} }
bool ui::Canvas::create(int width, int height) bool ui::Canvas::create(int width, int height)
{ {
@@ -473,7 +472,6 @@ bool ui::Canvas::create(int width, int height)
{ {
l.create(width, height, ""); l.create(width, height, "");
} }
m_latlong.create(width * 4, height * 2); // NOTE: w and h must be equal to make sense
return true; return true;
} }
@@ -506,7 +504,6 @@ void ui::Canvas::clear_context()
m_tex[i].destroy(); m_tex[i].destroy();
m_tex2[i].destroy(); m_tex2[i].destroy();
} }
m_latlong.destroy();
}; };
void ui::Canvas::export_equirectangular(std::string data_path) void ui::Canvas::export_equirectangular(std::string data_path)
@@ -522,6 +519,10 @@ void ui::Canvas::export_equirectangular(std::string data_path)
glViewport(0, 0, m_width, m_height); glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND); glDisable(GL_BLEND);
RTT m_latlong;
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
GLuint cube_id;
glGenTextures(1, &cube_id); glGenTextures(1, &cube_id);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id); glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
for (GLuint i = 0; i < 6; i++) for (GLuint i = 0; i < 6; i++)
@@ -603,6 +604,83 @@ void ui::Canvas::export_equirectangular(std::string data_path)
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride()); int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
} }
glDeleteTextures(1, &cube_id);
m_latlong.destroy();
// restore viewport and clear color states
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glViewport(vp[0], vp[1], vp[2], vp[3]);
glClearColor(cc[0], cc[1], cc[2], cc[3]);
glActiveTexture(GL_TEXTURE0);
}
void ui::Canvas::export_anim(std::string data_path)
{
// save viewport and clear color states
GLint vp[4];
GLfloat cc[4];
glGetIntegerv(GL_VIEWPORT, vp);
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
GLboolean blend = glIsEnabled(GL_BLEND);
// prepare common states
glViewport(0, 0, m_width, m_height);
glDisable(GL_BLEND);
glActiveTexture(GL_TEXTURE0);
RTT m_latlong;
m_latlong.create(m_width * 4, m_height * 2); // NOTE: w and h must be equal to make sense
GLuint cube_id;
glGenTextures(1, &cube_id);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
for (GLuint i = 0; i < 6; i++)
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGBA8, m_width, m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
int faces[]{
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, // front
GL_TEXTURE_CUBE_MAP_NEGATIVE_X, // right
GL_TEXTURE_CUBE_MAP_POSITIVE_Z, // back
GL_TEXTURE_CUBE_MAP_POSITIVE_X, // left
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, // top
GL_TEXTURE_CUBE_MAP_POSITIVE_Y, // bottom
};
for (auto layer_index : m_order)
{
for (int i = 0; i < 6; i++)
{
m_layers[layer_index].m_rtt[i].bindFramebuffer();
// copy result to cubemap
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
glCopyTexImage2D(faces[i], 0, GL_RGBA8, 0, 0, m_width, m_height, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
m_layers[layer_index].m_rtt[i].unbindFramebuffer();
}
glViewport(0, 0, m_latlong.getWidth(), m_latlong.getHeight());
m_latlong.clear({ 1, 1, 1, 1 });
m_latlong.bindFramebuffer();
ui::ShaderManager::use(kShader::Equirect);
ui::ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
m_sampler.bind(0);
m_plane.draw_fill();
m_sampler.unbind();
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
m_latlong.unbindFramebuffer();
{
auto latlong_data = std::make_unique<uint8_t[]>(m_latlong.bytes());
m_latlong.readTextureData(latlong_data.get());
static char name[128];
sprintf(name, "%s/latlong-frame%02d.png", data_path.c_str(), layer_index);
LOG("writing %s", name);
int ret = stbi_write_png(name, m_latlong.getWidth(), m_latlong.getHeight(), 4, latlong_data.get(), m_latlong.stride());
}
}
glDeleteTextures(1, &cube_id);
m_latlong.destroy();
// restore viewport and clear color states // restore viewport and clear color states
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND); blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
glViewport(vp[0], vp[1], vp[2], vp[3]); glViewport(vp[0], vp[1], vp[2], vp[3]);

View File

@@ -89,9 +89,6 @@ public:
I->m_state = mode; I->m_state = mode;
} }
GLuint cube_id;
RTT m_latlong;
std::vector<Layer::Snapshot> m_layers_snapshot; std::vector<Layer::Snapshot> m_layers_snapshot;
Canvas() { I = this; } Canvas() { I = this; }
@@ -110,6 +107,7 @@ public:
void snapshot_restore(); void snapshot_restore();
void clear_context(); void clear_context();
void export_equirectangular(std::string data_path); void export_equirectangular(std::string data_path);
void export_anim(std::string data_path);
void project_save(std::string data_path); void project_save(std::string data_path);
void project_open(std::string data_path); void project_open(std::string data_path);
ui::Image thumbnail_generate(int w, int h); ui::Image thumbnail_generate(int w, int h);

View File

@@ -8,10 +8,9 @@
bool LayoutManager::load(const char* path) bool LayoutManager::load(const char* path)
{ {
if (m_loaded) // if (m_loaded)
return true; // already loaded // return true; // already loaded
/*
#if !defined(__ANDROID__) #if !defined(__ANDROID__)
struct stat tmp_info; struct stat tmp_info;
if (stat(path, &tmp_info) != 0) if (stat(path, &tmp_info) != 0)
@@ -20,7 +19,6 @@ bool LayoutManager::load(const char* path)
return false; return false;
m_file_info = tmp_info; m_file_info = tmp_info;
#endif // __ANDROID__ #endif // __ANDROID__
*/
m_path = path; m_path = path;

View File

@@ -251,6 +251,17 @@ int Node::get_child_index(Node* n)
return -1; return -1;
} }
Node* Node::get_child_at(int index)
{
auto n = YGNodeGetChild(y_node, index);
for (auto& c : m_children)
{
if (c->y_node == n)
return c.get();
}
return nullptr;
}
glm::vec4 Node::get_children_rect() const glm::vec4 Node::get_children_rect() const
{ {
if (m_children.empty()) if (m_children.empty())

View File

@@ -184,6 +184,7 @@ public:
void move_child(Node* n, int index); void move_child(Node* n, int index);
void move_child_offset(Node* n, int offset); void move_child_offset(Node* n, int offset);
int get_child_index(Node* n); int get_child_index(Node* n);
Node* get_child_at(int index);
glm::vec4 get_children_rect() const; glm::vec4 get_children_rect() const;
void mouse_capture(); void mouse_capture();
void mouse_release(); void mouse_release();

View File

@@ -177,6 +177,11 @@ void NodePanelLayer::add_layer()
add_layer(s); add_layer(s);
} }
NodeLayer* NodePanelLayer::get_layer_at(int index)
{
return static_cast<NodeLayer*>(m_layers_container->get_child_at(index));
}
void NodePanelLayer::remove_layer(NodeLayer* layer) void NodePanelLayer::remove_layer(NodeLayer* layer)
{ {
auto it = std::find(m_layers.begin(), m_layers.end(), m_current_layer); auto it = std::find(m_layers.begin(), m_layers.end(), m_current_layer);

View File

@@ -51,6 +51,7 @@ public:
virtual void init() override; virtual void init() override;
void add_layer(); void add_layer();
void add_layer(const char* name); void add_layer(const char* name);
NodeLayer* get_layer_at(int index);
void remove_layer(NodeLayer* layer); void remove_layer(NodeLayer* layer);
void handle_layer_opacity(NodeLayer* target, float value); void handle_layer_opacity(NodeLayer* target, float value);
void handle_layer_visibility(NodeLayer* target, bool visible); void handle_layer_visibility(NodeLayer* target, bool visible);