added timeline slider and export animation frames
This commit is contained in:
@@ -393,6 +393,12 @@
|
||||
<!--<panel-color id="panel-color"/>-->
|
||||
</scroll>
|
||||
</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>
|
||||
<!-- status bar -->
|
||||
<!--<border height="30" width="100%" color=".15" border-color=".3" dir="row" pad="0 0 0 10" align="center">
|
||||
|
||||
@@ -47,7 +47,6 @@ bool App::mouse_scroll(float x, float y, float delta)
|
||||
e.m_scroll_delta = delta * 0.1f;
|
||||
auto ret = layout[main_id]->on_event(&e);
|
||||
layout[main_id]->update();
|
||||
LOG("wheel x %.2f y %.2f", x, y);
|
||||
return ret == kEventResult::Consumed;
|
||||
}
|
||||
bool App::mouse_cancel(int button)
|
||||
|
||||
@@ -232,7 +232,7 @@ void App::initLayout()
|
||||
button->on_click = [this,button](Node*) {
|
||||
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;
|
||||
}
|
||||
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");
|
||||
if (layout.m_loaded)
|
||||
|
||||
@@ -451,7 +451,6 @@ void ui::Canvas::resize(int width, int 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)
|
||||
{
|
||||
@@ -473,7 +472,6 @@ bool ui::Canvas::create(int width, int height)
|
||||
{
|
||||
l.create(width, height, "");
|
||||
}
|
||||
m_latlong.create(width * 4, height * 2); // NOTE: w and h must be equal to make sense
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -506,7 +504,6 @@ void ui::Canvas::clear_context()
|
||||
m_tex[i].destroy();
|
||||
m_tex2[i].destroy();
|
||||
}
|
||||
m_latlong.destroy();
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
glBindTexture(GL_TEXTURE_CUBE_MAP, cube_id);
|
||||
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());
|
||||
}
|
||||
|
||||
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
|
||||
blend ? glEnable(GL_BLEND) : glDisable(GL_BLEND);
|
||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||
|
||||
@@ -89,9 +89,6 @@ public:
|
||||
I->m_state = mode;
|
||||
}
|
||||
|
||||
GLuint cube_id;
|
||||
RTT m_latlong;
|
||||
|
||||
std::vector<Layer::Snapshot> m_layers_snapshot;
|
||||
|
||||
Canvas() { I = this; }
|
||||
@@ -110,6 +107,7 @@ public:
|
||||
void snapshot_restore();
|
||||
void clear_context();
|
||||
void export_equirectangular(std::string data_path);
|
||||
void export_anim(std::string data_path);
|
||||
void project_save(std::string data_path);
|
||||
void project_open(std::string data_path);
|
||||
ui::Image thumbnail_generate(int w, int h);
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
|
||||
bool LayoutManager::load(const char* path)
|
||||
{
|
||||
if (m_loaded)
|
||||
return true; // already loaded
|
||||
// if (m_loaded)
|
||||
// return true; // already loaded
|
||||
|
||||
/*
|
||||
#if !defined(__ANDROID__)
|
||||
struct stat tmp_info;
|
||||
if (stat(path, &tmp_info) != 0)
|
||||
@@ -20,7 +19,6 @@ bool LayoutManager::load(const char* path)
|
||||
return false;
|
||||
m_file_info = tmp_info;
|
||||
#endif // __ANDROID__
|
||||
*/
|
||||
|
||||
m_path = path;
|
||||
|
||||
|
||||
@@ -251,6 +251,17 @@ int Node::get_child_index(Node* n)
|
||||
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
|
||||
{
|
||||
if (m_children.empty())
|
||||
|
||||
@@ -184,6 +184,7 @@ public:
|
||||
void move_child(Node* n, int index);
|
||||
void move_child_offset(Node* n, int offset);
|
||||
int get_child_index(Node* n);
|
||||
Node* get_child_at(int index);
|
||||
glm::vec4 get_children_rect() const;
|
||||
void mouse_capture();
|
||||
void mouse_release();
|
||||
|
||||
@@ -177,6 +177,11 @@ void NodePanelLayer::add_layer()
|
||||
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)
|
||||
{
|
||||
auto it = std::find(m_layers.begin(), m_layers.end(), m_current_layer);
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
virtual void init() override;
|
||||
void add_layer();
|
||||
void add_layer(const char* name);
|
||||
NodeLayer* get_layer_at(int index);
|
||||
void remove_layer(NodeLayer* layer);
|
||||
void handle_layer_opacity(NodeLayer* target, float value);
|
||||
void handle_layer_visibility(NodeLayer* target, bool visible);
|
||||
|
||||
Reference in New Issue
Block a user