added timeline slider and export animation frames
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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]);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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())
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user