diff --git a/src/node_panel_brush.cpp b/src/node_panel_brush.cpp index c003f84..b0f0823 100644 --- a/src/node_panel_brush.cpp +++ b/src/node_panel_brush.cpp @@ -40,6 +40,29 @@ void NodeButtonBrush::draw() NodeButtonCustom::draw(); } +bool NodeButtonBrush::read(BinaryStreamReader& r) +{ + Serializer::Descriptor d; + r >> d; + d.value("brush_name", brush_name); + d.value("high_path", high_path); + d.value("thumb_path", thumb_path); + d.value("m_user_brush", m_user_brush); + return true; +} + +void NodeButtonBrush::write(BinaryStreamWriter& w) const +{ + Serializer::Descriptor d; + d.class_id = "brush"; + d.name = L"Brush class"; + d.props["brush_name"] = std::make_shared(brush_name); + d.props["high_path"] = std::make_shared(high_path); + d.props["thumb_path"] = std::make_shared(thumb_path); + d.props["m_user_brush"] = std::make_shared(m_user_brush); + w << d; +} + Node* NodePanelBrush::clone_instantiate() const { return new NodePanelBrush(); @@ -145,7 +168,19 @@ void NodePanelBrush::init() }; m_container = find("brushes"); - restore(); + + if (Asset::exist(App::I.data_path + "/settings/" + m_dir_name + ".bin") && !restore()) + { + auto mb = App::I.message_box("Brushes", "Could not read brush textures file, it will be deleted.", true); + mb->btn_ok->on_click = [this, mb](Node*) { + Asset::delete_file(App::I.data_path + "/settings/" + m_dir_name + ".bin"); + mb->destroy(); + }; + mb->btn_cancel->on_click = [mb](Node*) { + mb->destroy(); + }; + } + if (m_container->m_children.empty() && !m_dir_name.empty()) { auto icons = Asset::list_files("data/" + m_dir_name, ".*\\.png$"); @@ -251,33 +286,21 @@ std::string NodePanelBrush::get_thumb_path(int index) const bool NodePanelBrush::save() { - auto path = App::I.data_path + "/settings/" + m_dir_name + ".bin"; - if (FILE* fp = fopen(path.c_str(), "wb")) + std::ofstream f(App::I.data_path + "/settings/" + m_dir_name + ".bin", std::ios::binary); + if (f.good()) { - header_t h; - h.brushes = m_container->m_children.size(); - fwrite(&h, sizeof(h), 1, fp); + BinaryStreamWriter sw; + sw.init(); + sw.wstring_raw("PPVR"); + sw.wu16(0); + sw.wu16(1); + sw.wu32(m_container->m_children.size()); for (const auto& child : m_container->m_children) { auto b = std::static_pointer_cast(child); - item_t i; - i.m_name_len = b->brush_name.size(); - i.m_high_len = b->high_path.size(); - i.m_thumb_len = b->thumb_path.size(); - fwrite(&i, sizeof(i), 1, fp); - fwrite(b->brush_name.c_str(), 1, b->brush_name.size(), fp); - fwrite(b->high_path.c_str(), 1, b->high_path.size(), fp); - fwrite(b->thumb_path.c_str(), 1, b->thumb_path.size(), fp); + sw << *b; } - for (const auto& d : m_deleted) - { - item_t i; - i.m_high_len = d.size(); - i.m_thumb_len = 0; - fwrite(&i, sizeof(i), 1, fp); - fwrite(d.c_str(), 1, d.size(), fp); - } - fclose(fp); + f.write((char*)sw.m_data.data(), sw.m_data.size()); return true; } return false; @@ -285,51 +308,50 @@ bool NodePanelBrush::save() bool NodePanelBrush::restore() { + Asset f; auto path = App::I.data_path + "/settings/" + m_dir_name + ".bin"; - if (FILE* fp = fopen(path.c_str(), "rb")) + if (f.open(path.c_str())) { - header_t h; - fread(&h, sizeof(h), 1, fp); - if (strcmp(h.magic, "PPBR") != 0) + f.read_all(); + + BinaryStreamReader sr; + sr.init(f.m_data, f.m_len); + + // sanity checks + if (sr.rstring(4) != "PPVR") { - fclose(fp); - LOG("Brushes file malformed: %s", path.c_str()); - return false; + LOG("PPVR tag not found") + return false; } - if (h.version < 0 || h.version > 0) + auto vmaj = sr.ru16(); + auto vmin = sr.ru16(); + if (vmaj != 0 && vmin != 1) { - fclose(fp); - LOG("Brushes file version %d not supported: %s", h.version, path.c_str()); + LOG("unrecognised version %d.$d", vmaj, vmin); return false; } - for (int k = 0; k < h.brushes; k++) - { - item_t i; - fread(&i, sizeof(i), 1, fp); - std::string name(i.m_name_len, 0); - std::string path_high(i.m_high_len, 0); - std::string path_thumb(i.m_thumb_len, 0); - fread((char*)name.c_str(), 1, name.size(), fp); - fread((char*)path_high.c_str(), 1, path_high.size(), fp); - fread((char*)path_thumb.c_str(), 1, path_thumb.size(), fp); + auto count = sr.ru32(); - if (Asset::exist(path_high)) + for (int k = 0; k < count; k++) + { + auto b = std::make_shared(); + if (!b->read(sr)) { - NodeButtonBrush* brush = new NodeButtonBrush; - m_container->add_child(brush); - brush->init(); - brush->create(); - brush->loaded(); - brush->set_icon(path_thumb.c_str()); - brush->thumb_path = path_thumb; - brush->high_path = path_high; - brush->brush_name = name; - brush->m_user_brush = i.m_user_brush; - brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1); + LOG("error deserializing the button brush"); + return false; + } + + if (Asset::exist(b->high_path)) + { + m_container->add_child(b); + b->init(); + b->create(); + b->loaded(); + b->set_icon(b->thumb_path.c_str()); + b->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1); } } - fclose(fp); return true; } return false; @@ -481,8 +503,8 @@ void NodePanelBrushPreset::handle_click(Node* target) bool NodePanelBrushPreset::save() { - auto path = App::I.data_path + "/settings/presets.bin"; - if (FILE* fp = fopen(path.c_str(), "wb")) + std::ofstream f(App::I.data_path + "/settings/presets.bin", std::ios::binary); + if (f.good()) { BinaryStreamWriter sw; sw.init(); @@ -493,11 +515,9 @@ bool NodePanelBrushPreset::save() for (int ci = 0; ci < m_container->m_children.size(); ci++) { auto bpi = static_cast(m_container->get_child_at(ci)); - auto& b = bpi->m_brush; - sw << *b; + sw << *bpi->m_brush; } - fwrite(sw.m_data.data(), sw.m_data.size(), 1, fp); - fclose(fp); + f.write((char*)sw.m_data.data(), sw.m_data.size()); return true; } return false; @@ -505,23 +525,19 @@ bool NodePanelBrushPreset::save() bool NodePanelBrushPreset::restore() { + Asset f; auto path = App::I.data_path + "/settings/presets.bin"; - if (FILE* fp = fopen(path.c_str(), "rb")) + if (f.open(path.c_str())) { - fseek(fp, 0, SEEK_END); - size_t sz = ftell(fp); - fseek(fp, 0, SEEK_SET); - std::vector data(sz); - fread(data.data(), 1, sz, fp); + f.read_all(); BinaryStreamReader sr; - sr.init(data.data(), sz); + sr.init(f.m_data, f.m_len); // sanity checks if (sr.rstring(4) != "PPVR") { LOG("PPVR tag not found") - fclose(fp); return false; } auto vmaj = sr.ru16(); @@ -529,7 +545,6 @@ bool NodePanelBrushPreset::restore() if (vmaj != 0 && vmin != 1) { LOG("unrecognised version %d.$d", vmaj, vmin); - fclose(fp); return false; } @@ -541,7 +556,6 @@ bool NodePanelBrushPreset::restore() if (!b->read(sr)) { LOG("error deserializing the brush"); - fclose(fp); return false; } @@ -562,7 +576,6 @@ bool NodePanelBrushPreset::restore() brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1); } } - fclose(fp); return true; } return false; diff --git a/src/node_panel_brush.h b/src/node_panel_brush.h index 401b3fd..8730476 100644 --- a/src/node_panel_brush.h +++ b/src/node_panel_brush.h @@ -6,8 +6,9 @@ #include "brush.h" #include "node_scroll.h" #include "node_text.h" +#include "serializer.h" -class NodeButtonBrush : public NodeButtonCustom +class NodeButtonBrush : public NodeButtonCustom, public Serializer::Type { public: bool m_selected = false; @@ -22,6 +23,8 @@ public: virtual void init() override; void set_icon(const char* path); virtual void draw() override; + virtual bool read(BinaryStreamReader& r) override; + virtual void write(BinaryStreamWriter& w) const override; }; class NodePanelBrush : public Node