implement frames save and open from ppi
This commit is contained in:
175
src/canvas.cpp
175
src/canvas.cpp
@@ -5,6 +5,8 @@
|
||||
#include "texture.h"
|
||||
#include "node_progress_bar.h"
|
||||
#include <thread>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Foundation/Foundation.h>
|
||||
@@ -2117,8 +2119,13 @@ bool Canvas::project_save_thread(std::string file_path, bool show_progress)
|
||||
int n_layers = (int)m_layers.size();
|
||||
fwrite(&n_layers, sizeof(int), 1, fp);
|
||||
|
||||
int n_frames = std::accumulate(m_layers.begin(), m_layers.end(), 0,
|
||||
[](int tot, auto& l) { return tot + l->m_frames.size(); });
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
fwrite(&n_frames, sizeof(int), 1, fp);
|
||||
|
||||
int progress = 0;
|
||||
int total = (int)m_layers.size() * 6;
|
||||
int total = n_frames * 6;
|
||||
|
||||
for (int i = 0; i < (int)m_layers.size(); i++)
|
||||
{
|
||||
@@ -2132,44 +2139,57 @@ bool Canvas::project_save_thread(std::string file_path, bool show_progress)
|
||||
fwrite(&name_len, sizeof(int), 1, fp);
|
||||
fwrite(m_layers[i]->m_name.data(), name_len, 1, fp);
|
||||
|
||||
if (ppi_header.doc_version.minor > 1)
|
||||
if (ppi_header.doc_version.minor >= 2)
|
||||
{
|
||||
fwrite(&m_layers[i]->m_blend_mode, sizeof(int), 1, fp);
|
||||
fwrite(&m_layers[i]->m_alpha_locked, sizeof(bool), 1, fp);
|
||||
fwrite(&m_layers[i]->m_visible, sizeof(bool), 1, fp);
|
||||
}
|
||||
|
||||
m_layers[i]->optimize();
|
||||
auto snap = m_layers[i]->snapshot();
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
|
||||
int frames = 1;
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
{
|
||||
int has_data = snap.m_dirty_face[plane_index] ? 1 : 0;
|
||||
fwrite(&has_data, sizeof(int), 1, fp);
|
||||
if (has_data)
|
||||
frames = (int)m_layers[i]->m_frames.size();
|
||||
fwrite(&frames, sizeof(int), 1, fp);
|
||||
}
|
||||
|
||||
for (int fi = 0; fi < frames; fi++)
|
||||
{
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
fwrite(&m_layers[i]->m_frames[fi].m_duration, sizeof(int), 1, fp);
|
||||
|
||||
m_layers[i]->optimize(fi);
|
||||
auto snap = m_layers[i]->snapshot(fi);
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
glm::ivec4 b = snap.m_dirty_box[plane_index];
|
||||
glm::vec2 sz = zw(b) - xy(b);
|
||||
int box[4] = { b.x, b.y, b.z, b.w };
|
||||
fwrite(&box, sizeof(box), 1, fp);
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
auto callback = [](void *context, void *data, int size)
|
||||
int has_data = snap.m_dirty_face[plane_index] ? 1 : 0;
|
||||
fwrite(&has_data, sizeof(int), 1, fp);
|
||||
if (has_data)
|
||||
{
|
||||
std::vector<uint8_t>* buffer = static_cast<std::vector<uint8_t>*>(context);
|
||||
buffer->insert(buffer->end(), (uint8_t*)data, (uint8_t*)data + size);
|
||||
};
|
||||
int ret = stbi_write_png_to_func(callback, &compressed, sz.x, sz.y, 4, snap.image[plane_index].get(), sz.x * 4);
|
||||
|
||||
int data_size = (int)compressed.size();
|
||||
fwrite(&data_size, sizeof(int), 1, fp);
|
||||
|
||||
fwrite(compressed.data(), 1, compressed.size(), fp);
|
||||
glm::ivec4 b = snap.m_dirty_box[plane_index];
|
||||
glm::vec2 sz = zw(b) - xy(b);
|
||||
int box[4] = { b.x, b.y, b.z, b.w };
|
||||
fwrite(&box, sizeof(box), 1, fp);
|
||||
|
||||
std::vector<uint8_t> compressed;
|
||||
auto callback = [](void* context, void* data, int size)
|
||||
{
|
||||
std::vector<uint8_t>* buffer = static_cast<std::vector<uint8_t>*>(context);
|
||||
buffer->insert(buffer->end(), (uint8_t*)data, (uint8_t*)data + size);
|
||||
};
|
||||
int ret = stbi_write_png_to_func(callback, &compressed, sz.x, sz.y, 4, snap.image[plane_index].get(), sz.x * 4);
|
||||
|
||||
int data_size = (int)compressed.size();
|
||||
fwrite(&data_size, sizeof(int), 1, fp);
|
||||
|
||||
fwrite(compressed.data(), 1, compressed.size(), fp);
|
||||
}
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
if (show_progress)
|
||||
pb->m_progress->SetWidthP(p);
|
||||
LOG("progress: %f", p);
|
||||
}
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
if (show_progress)
|
||||
pb->m_progress->SetWidthP(p);
|
||||
LOG("progress: %f", p);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
@@ -2273,13 +2293,16 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
|
||||
int n_layers = 0;
|
||||
fread(&n_layers, sizeof(int), 1, fp);
|
||||
|
||||
int n_frames = 1;
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
fread(&n_frames, sizeof(int), 1, fp);
|
||||
|
||||
const int bytes = m_width * m_height * 4;
|
||||
Layer::Snapshot snap;
|
||||
snap.create(m_width, m_height); // allocate single data, no box should be bigger
|
||||
|
||||
int progress = 0;
|
||||
int total = n_layers * 6;
|
||||
int total = n_frames * 6;
|
||||
|
||||
for (auto& l : m_layers)
|
||||
l->destroy();
|
||||
@@ -2307,52 +2330,63 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
std::string name(name_len, '\0');
|
||||
fread((char*)name.data(), name_len, 1, fp);
|
||||
|
||||
if (ppi_header.doc_version.minor > 1)
|
||||
if (ppi_header.doc_version.minor >= 2)
|
||||
{
|
||||
fread(&layer->m_blend_mode, sizeof(int), 1, fp);
|
||||
fread(&layer->m_alpha_locked, sizeof(bool), 1, fp);
|
||||
fread(&layer->m_visible, sizeof(bool), 1, fp);
|
||||
}
|
||||
|
||||
snap.clear();
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
int has_data;
|
||||
fread(&has_data, sizeof(int), 1, fp);
|
||||
snap.m_dirty_face[plane_index] = has_data;
|
||||
if (has_data)
|
||||
{
|
||||
int b[4];
|
||||
fread(&b, sizeof(b), 1, fp);
|
||||
snap.m_dirty_box[plane_index] = glm::vec4(b[0], b[1], b[2], b[3]);
|
||||
glm::vec2 sz = zw(snap.m_dirty_box[plane_index]) - xy(snap.m_dirty_box[plane_index]);
|
||||
|
||||
int data_size;
|
||||
fread(&data_size, sizeof(int), 1, fp);
|
||||
std::vector<uint8_t> compressed(data_size);
|
||||
|
||||
fread(compressed.data(), 1, data_size, fp);
|
||||
int imgw, imgh, imgc;
|
||||
uint8_t* rgba = stbi_load_from_memory(compressed.data(), data_size, &imgw, &imgh, &imgc, 4);
|
||||
if (rgba)
|
||||
{
|
||||
std::copy(rgba, rgba + (imgw*imgh * 4), snap.image[plane_index].get());
|
||||
delete rgba;
|
||||
}
|
||||
}
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
|
||||
if (App::I->layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
}
|
||||
}
|
||||
int frames = 1;
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
fread(&frames, sizeof(int), 1, fp);
|
||||
|
||||
layer->create(m_width, m_height, name.c_str());
|
||||
layer->restore(snap);
|
||||
|
||||
for (int fi = 0; fi < frames; fi++)
|
||||
{
|
||||
if (fi > 0)
|
||||
layer->add_frame();
|
||||
if (ppi_header.doc_version.minor >= 3)
|
||||
fread(&layer->m_frames[fi].m_duration, sizeof(int), 1, fp);
|
||||
snap.clear();
|
||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||
{
|
||||
int has_data;
|
||||
fread(&has_data, sizeof(int), 1, fp);
|
||||
snap.m_dirty_face[plane_index] = has_data;
|
||||
if (has_data)
|
||||
{
|
||||
int b[4];
|
||||
fread(&b, sizeof(b), 1, fp);
|
||||
snap.m_dirty_box[plane_index] = glm::vec4(b[0], b[1], b[2], b[3]);
|
||||
glm::vec2 sz = zw(snap.m_dirty_box[plane_index]) - xy(snap.m_dirty_box[plane_index]);
|
||||
|
||||
int data_size;
|
||||
fread(&data_size, sizeof(int), 1, fp);
|
||||
std::vector<uint8_t> compressed(data_size);
|
||||
|
||||
fread(compressed.data(), 1, data_size, fp);
|
||||
int imgw, imgh, imgc;
|
||||
uint8_t* rgba = stbi_load_from_memory(compressed.data(), data_size, &imgw, &imgh, &imgc, 4);
|
||||
if (rgba)
|
||||
{
|
||||
std::copy(rgba, rgba + (imgw * imgh * 4), snap.image[plane_index].get());
|
||||
delete rgba;
|
||||
}
|
||||
}
|
||||
|
||||
progress++;
|
||||
float p = (float)progress / total * 100.f;
|
||||
LOG("progress: %f", p);
|
||||
|
||||
if (App::I->layout.m_loaded)
|
||||
{
|
||||
pb->m_progress->SetWidthP(p);
|
||||
}
|
||||
}
|
||||
layer->restore(snap, fi);
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(tmp_layers, m_layers);
|
||||
@@ -2377,6 +2411,7 @@ bool Canvas::project_open_thread(std::string file_path)
|
||||
{
|
||||
pb->destroy();
|
||||
App::I->title_update();
|
||||
App::I->animation->load_layers();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user