save brushes settings
This commit is contained in:
11
src/app.cpp
11
src/app.cpp
@@ -143,6 +143,10 @@ void App::initLog()
|
||||
{
|
||||
LOG("error creating thumbs path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
}
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/settings"] withIntermediateDirectories:YES attributes:nil error:&err])
|
||||
{
|
||||
LOG("error creating settings path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
}
|
||||
#elif defined(__OSX__)
|
||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSPicturesDirectory, NSUserDomainMask, YES);
|
||||
NSString* docpath = [(NSString*)[paths objectAtIndex:0] stringByAppendingString:@"/PanoPainter"];
|
||||
@@ -170,6 +174,10 @@ void App::initLog()
|
||||
{
|
||||
LOG("error creating thumbs path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
}
|
||||
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/settings"] withIntermediateDirectories:YES attributes:nil error:&err])
|
||||
{
|
||||
LOG("error creating settings path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
|
||||
}
|
||||
#elif defined(_WIN32)
|
||||
//CHAR my_documents[MAX_PATH];
|
||||
//HRESULT result = SHGetFolderPathA(NULL, CSIDL_PERSONAL, NULL, SHGFP_TYPE_CURRENT, my_documents);
|
||||
@@ -209,6 +217,9 @@ void App::initLog()
|
||||
|
||||
if (!PathFileExistsA((data_path + "\\brushes\\thumbs").c_str()))
|
||||
CreateDirectoryA((data_path + "\\brushes\\thumbs").c_str(), NULL);
|
||||
|
||||
if (!PathFileExistsA((data_path + "\\settings").c_str()))
|
||||
CreateDirectoryA((data_path + "\\settings").c_str(), NULL);
|
||||
#endif
|
||||
|
||||
// TODO: save this path somewhere in the settings, don't overwrite every start
|
||||
|
||||
@@ -124,7 +124,7 @@ void App::dialog_newdoc()
|
||||
App::I.hideKeyboard();
|
||||
};
|
||||
|
||||
if (Asset::exist(path, false))
|
||||
if (Asset::exist(path))
|
||||
{
|
||||
// ask confirm is file already exist
|
||||
auto msgbox = new NodeMessageBox();
|
||||
@@ -331,7 +331,7 @@ void App::dialog_save_ver()
|
||||
static char tmp_name[256];
|
||||
sprintf(tmp_name, "%s.%02d", base.c_str(), i);
|
||||
next = tmp_name;
|
||||
if (Asset::exist(doc_dir + "/" + next + ".ppi", false))
|
||||
if (Asset::exist(doc_dir + "/" + next + ".ppi"))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
@@ -382,7 +382,7 @@ void App::dialog_save()
|
||||
App::I.hideKeyboard();
|
||||
};
|
||||
|
||||
if (Asset::exist(path, false))
|
||||
if (Asset::exist(path))
|
||||
{
|
||||
// ask confirm is file already exist
|
||||
auto msgbox = new NodeMessageBox();
|
||||
|
||||
@@ -18,9 +18,9 @@ bool Asset::delete_file(const std::string& path)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Asset::exist(std::string path, bool is_asset)
|
||||
bool Asset::exist(std::string path)
|
||||
{
|
||||
if (is_asset)
|
||||
if (Asset::is_asset(path))
|
||||
{
|
||||
Asset asset;
|
||||
if (asset.open(path.c_str()))
|
||||
|
||||
@@ -8,7 +8,7 @@ public:
|
||||
AAsset* m_asset = nullptr;
|
||||
#endif
|
||||
static std::vector<std::string> list_files(std::string folder, bool is_asset, const std::string& filter_regex);
|
||||
static bool exist(std::string path, bool is_asset);
|
||||
static bool exist(std::string path);
|
||||
static bool delete_file(const std::string& path);
|
||||
static std::string absolute(const std::string& path);
|
||||
static bool is_asset(const std::string& path);
|
||||
|
||||
@@ -266,7 +266,7 @@ void Node::add_child(std::shared_ptr<Node> n)
|
||||
|
||||
void Node::add_child(std::shared_ptr<Node> n, int index)
|
||||
{
|
||||
m_children.push_back(n);
|
||||
m_children.insert(m_children.begin() + index, n);
|
||||
n->parent = this;
|
||||
n->m_manager = m_manager;
|
||||
YGNodeInsertChild(y_node, n->y_node, index);
|
||||
@@ -301,6 +301,11 @@ void Node::move_child(Node* n, int index)
|
||||
{
|
||||
YGNodeRemoveChild(y_node, n->y_node);
|
||||
YGNodeInsertChild(y_node, n->y_node, index);
|
||||
auto it = std::find_if(m_children.begin(), m_children.end(),
|
||||
[n](const std::shared_ptr<Node>& o) { return o.get() == n; });
|
||||
auto tmp = *it; // copy the ptr before removing it
|
||||
m_children.erase(it);
|
||||
m_children.insert(m_children.begin() + index, tmp);
|
||||
}
|
||||
|
||||
void Node::move_child_offset(Node* n, int offset)
|
||||
|
||||
@@ -47,7 +47,6 @@ Node* NodePanelBrush::clone_instantiate() const
|
||||
void NodePanelBrush::init()
|
||||
{
|
||||
init_template("tpl-panel-brushes");
|
||||
static auto icons = Asset::list_files("data/thumbs", true, ".*\\.png$");
|
||||
|
||||
m_btn_add = find<NodeButtonCustom>("btn-add");
|
||||
m_btn_add->on_click = [this](Node*) {
|
||||
@@ -80,10 +79,12 @@ void NodePanelBrush::init()
|
||||
brush->thumb_path = path_thumb;
|
||||
brush->high_path = path_high;
|
||||
brush->brush_name = name;
|
||||
brush->m_user_brush = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
|
||||
app_redraw();
|
||||
async_end();
|
||||
save();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -94,8 +95,12 @@ void NodePanelBrush::init()
|
||||
if (m_current)
|
||||
{
|
||||
int idx = m_container->get_child_index(m_current);
|
||||
Asset::delete_file(m_current->thumb_path);
|
||||
Asset::delete_file(m_current->high_path);
|
||||
if (m_current->m_user_brush)
|
||||
{
|
||||
// only delete user brushes
|
||||
Asset::delete_file(m_current->thumb_path);
|
||||
Asset::delete_file(m_current->high_path);
|
||||
}
|
||||
m_container->remove_child(m_current);
|
||||
if (m_container->m_children.size() > 0)
|
||||
{
|
||||
@@ -109,12 +114,37 @@ void NodePanelBrush::init()
|
||||
{
|
||||
m_current = nullptr;
|
||||
}
|
||||
save();
|
||||
}
|
||||
};
|
||||
|
||||
if ((m_container = find<NodeScroll>("brushes")))
|
||||
m_btn_up = find<NodeButtonCustom>("btn-up");
|
||||
m_btn_up->on_click = [this](Node*) {
|
||||
if (m_current)
|
||||
{
|
||||
int idx = m_container->get_child_index(m_current);
|
||||
idx = std::max(0, std::min(idx - 1, (int)m_container->m_children.size() - 1));
|
||||
m_container->move_child(m_current, idx);
|
||||
save();
|
||||
}
|
||||
};
|
||||
|
||||
m_btn_down = find<NodeButtonCustom>("btn-down");
|
||||
m_btn_down->on_click = [this](Node*) {
|
||||
if (m_current)
|
||||
{
|
||||
int idx = m_container->get_child_index(m_current);
|
||||
idx = std::max(0, std::min(idx + 1, (int)m_container->m_children.size() - 1));
|
||||
m_container->move_child(m_current, idx);
|
||||
save();
|
||||
}
|
||||
};
|
||||
|
||||
m_container = find<NodeScroll>("brushes");
|
||||
restore();
|
||||
if (m_container->m_children.empty())
|
||||
{
|
||||
int count = 0;
|
||||
auto icons = Asset::list_files("data/brushes", true, ".*\\.png$");
|
||||
for (auto& i : icons)
|
||||
{
|
||||
std::string path = "data/thumbs/" + i;
|
||||
@@ -128,6 +158,7 @@ void NodePanelBrush::init()
|
||||
brush->thumb_path = path;
|
||||
brush->high_path = path_hi;
|
||||
brush->brush_name = i;
|
||||
brush->m_user_brush = false; // system brush, cannot be deleted from file
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
}
|
||||
|
||||
@@ -145,9 +176,11 @@ void NodePanelBrush::init()
|
||||
brush->thumb_path = path_thumb;
|
||||
brush->high_path = path_high;
|
||||
brush->brush_name = i;
|
||||
brush->m_user_brush = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
|
||||
kEventResult NodePanelBrush::handle_event(Event* e)
|
||||
@@ -203,25 +236,94 @@ std::string NodePanelBrush::get_thumb_path(int index) const
|
||||
return ((NodeButtonBrush*)m_container->m_children[index].get())->thumb_path;
|
||||
}
|
||||
|
||||
// select the current brush based on the texture id
|
||||
//void NodePanelBrush::select_brush(int brush_id)
|
||||
//{
|
||||
// if (m_current)
|
||||
// m_current->m_selected = false;
|
||||
// for (auto b : m_brushes)
|
||||
// {
|
||||
// if (b->m_brushID == brush_id)
|
||||
// {
|
||||
// b->m_selected = true;
|
||||
// m_current = b;
|
||||
// TextureManager::load(b->high_path.c_str(), true);
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
bool NodePanelBrush::save()
|
||||
{
|
||||
auto path = App::I.data_path + "/settings/brushes.bin";
|
||||
if (FILE* fp = fopen(path.c_str(), "wb"))
|
||||
{
|
||||
header_t h;
|
||||
h.brushes = m_container->m_children.size();
|
||||
fwrite(&h, sizeof(h), 1, fp);
|
||||
for (const auto& child : m_container->m_children)
|
||||
{
|
||||
auto b = std::static_pointer_cast<NodeButtonBrush>(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);
|
||||
}
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NodePanelBrush::restore()
|
||||
{
|
||||
auto path = App::I.data_path + "/settings/brushes.bin";
|
||||
if (FILE* fp = fopen(path.c_str(), "rb"))
|
||||
{
|
||||
header_t h;
|
||||
fread(&h, sizeof(h), 1, fp);
|
||||
if (strcmp(h.magic, "PPBR") != 0)
|
||||
{
|
||||
fclose(fp);
|
||||
LOG("Brushes file malformed: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
if (h.version < 0 || h.version > 0)
|
||||
{
|
||||
fclose(fp);
|
||||
LOG("Brushes file version %d not supported: %s", h.version, path.c_str());
|
||||
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);
|
||||
|
||||
if (Asset::exist(path_high))
|
||||
{
|
||||
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 = true;
|
||||
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
Node* NodeBrushPresetItem::clone_instantiate() const
|
||||
{
|
||||
return new NodeBrushPresetItem();
|
||||
@@ -244,11 +346,6 @@ void NodeBrushPresetItem::draw()
|
||||
NodeButtonCustom::draw();
|
||||
}
|
||||
|
||||
NodeBrushPresetItem::~NodeBrushPresetItem()
|
||||
{
|
||||
bool u = m_brush.unique();
|
||||
}
|
||||
|
||||
//---
|
||||
|
||||
Node* NodePanelBrushPreset::clone_instantiate() const
|
||||
@@ -361,15 +458,15 @@ void NodePanelBrushPreset::handle_click(Node* target)
|
||||
|
||||
bool NodePanelBrushPreset::save()
|
||||
{
|
||||
auto path = App::I.data_path + "/presets.bin";
|
||||
auto path = App::I.data_path + "/settings/presets.bin";
|
||||
if (FILE* fp = fopen(path.c_str(), "wb"))
|
||||
{
|
||||
header_t h;
|
||||
h.count = m_container->m_children.size();
|
||||
fwrite(&h, sizeof(h), 1, fp);
|
||||
for (const auto& child : m_container->m_children)
|
||||
for (int ci = 0; ci < m_container->m_children.size(); ci++)
|
||||
{
|
||||
auto b = std::static_pointer_cast<NodeBrushPresetItem>(child);
|
||||
auto b = static_cast<NodeBrushPresetItem*>(m_container->get_child_at(ci));
|
||||
item_t i;
|
||||
i.m_name_len = b->m_brush->m_name.size();
|
||||
i.m_brush_path_len = b->m_brush->m_brush_path.size();
|
||||
@@ -409,18 +506,31 @@ bool NodePanelBrushPreset::save()
|
||||
fwrite(b->m_brush->m_stencil_path.c_str(), 1, b->m_brush->m_stencil_path.size(), fp);
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NodePanelBrushPreset::restore()
|
||||
{
|
||||
auto path = App::I.data_path + "/presets.bin";
|
||||
auto path = App::I.data_path + "/settings/presets.bin";
|
||||
if (FILE* fp = fopen(path.c_str(), "rb"))
|
||||
{
|
||||
header_t h;
|
||||
fread(&h, sizeof(h), 1, fp);
|
||||
|
||||
if (strcmp(h.magic, "PPPR") != 0)
|
||||
{
|
||||
fclose(fp);
|
||||
LOG("Presets file malformed: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
if (h.version < 0 || h.version > 0)
|
||||
{
|
||||
fclose(fp);
|
||||
LOG("Presets file version %d not supported: %s", h.version, path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int k = 0; k < h.count; k++)
|
||||
{
|
||||
item_t i;
|
||||
@@ -462,25 +572,28 @@ bool NodePanelBrushPreset::restore()
|
||||
fread((char*)b->m_brush_thumb_path.c_str(), 1, b->m_brush_thumb_path.size(), fp);
|
||||
fread((char*)b->m_stencil_path.c_str(), 1, b->m_stencil_path.size(), fp);
|
||||
|
||||
b->load_texture(b->m_brush_path, b->m_brush_thumb_path);
|
||||
if (!b->m_stencil_path.empty())
|
||||
b->load_stencil(b->m_stencil_path);
|
||||
if (b->load_texture(b->m_brush_path, b->m_brush_thumb_path))
|
||||
{
|
||||
if (!b->m_stencil_path.empty())
|
||||
b->load_stencil(b->m_stencil_path);
|
||||
|
||||
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
|
||||
m_container->add_child(brush);
|
||||
brush->init();
|
||||
brush->create();
|
||||
brush->loaded();
|
||||
brush->thumb_path = b->m_brush_thumb_path;
|
||||
brush->high_path = b->m_brush_path;
|
||||
brush->m_brush = b;
|
||||
brush->m_brush->m_tip_size = .05f;
|
||||
brush->m_preview->m_brush = b;
|
||||
brush->m_preview->draw_stroke();
|
||||
brush->m_thumb->set_image(brush->m_brush->m_brush_thumb_path);
|
||||
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
||||
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
|
||||
m_container->add_child(brush);
|
||||
brush->init();
|
||||
brush->create();
|
||||
brush->loaded();
|
||||
brush->thumb_path = b->m_brush_thumb_path;
|
||||
brush->high_path = b->m_brush_path;
|
||||
brush->m_brush = b;
|
||||
brush->m_brush->m_tip_size = .05f;
|
||||
brush->m_preview->m_brush = b;
|
||||
brush->m_preview->draw_stroke();
|
||||
brush->m_thumb->set_image(brush->m_brush->m_brush_thumb_path);
|
||||
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,13 @@
|
||||
class NodeButtonBrush : public NodeButtonCustom
|
||||
{
|
||||
public:
|
||||
//int m_brushID;
|
||||
bool m_selected = false;
|
||||
// whether the brush is a system default
|
||||
// or user imported so it can be deleted from file
|
||||
bool m_user_brush = false;
|
||||
std::string brush_name;
|
||||
std::string high_path;
|
||||
std::string thumb_path;
|
||||
//uint16_t high_id;
|
||||
NodeImage* img;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void init() override;
|
||||
@@ -24,13 +25,26 @@ public:
|
||||
|
||||
class NodePanelBrush : public Node
|
||||
{
|
||||
//std::vector<NodeButtonBrush*> m_brushes;
|
||||
// brushes that are marked as deleted but file still exists
|
||||
std::vector<std::string> m_deleted;
|
||||
NodeButtonBrush* m_current = nullptr;
|
||||
NodeScroll* m_container;
|
||||
NodeButtonCustom* m_btn_add;
|
||||
NodeButtonCustom* m_btn_up;
|
||||
NodeButtonCustom* m_btn_down;
|
||||
NodeButtonCustom* m_btn_remove;
|
||||
struct header_t {
|
||||
char magic[5]{ 'P', 'P', 'B', 'R', 0 };
|
||||
uint16_t version = 0;
|
||||
uint16_t brushes = 0;
|
||||
uint16_t deleted = 0;
|
||||
};
|
||||
struct item_t {
|
||||
int m_name_len = 0;
|
||||
int m_high_len = 0;
|
||||
int m_thumb_len = 0;
|
||||
bool m_deleted = false;
|
||||
};
|
||||
public:
|
||||
std::function<void(Node* target, int index)> on_brush_changed;
|
||||
std::function<void(Node* target)> on_popup_close;
|
||||
@@ -41,7 +55,8 @@ public:
|
||||
int find_brush(const std::string& name) const;
|
||||
std::string get_texture_path(int index) const;
|
||||
std::string get_thumb_path(int index) const;
|
||||
//void select_brush(int brush_id);
|
||||
bool save();
|
||||
bool restore();
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@@ -58,12 +73,10 @@ public:
|
||||
virtual Node* clone_instantiate() const override;
|
||||
virtual void init() override;
|
||||
virtual void draw() override;
|
||||
virtual ~NodeBrushPresetItem();
|
||||
};
|
||||
|
||||
class NodePanelBrushPreset : public Node
|
||||
{
|
||||
//std::vector<NodeBrushPresetItem*> m_brushes;
|
||||
NodeBrushPresetItem* m_current = nullptr;
|
||||
Node* m_container;
|
||||
NodeButtonCustom* m_btn_add;
|
||||
@@ -72,17 +85,15 @@ class NodePanelBrushPreset : public Node
|
||||
NodeButtonCustom* m_btn_delete;
|
||||
NodeButtonCustom* m_btn_save;
|
||||
struct header_t {
|
||||
char magic[4]{ 'P', 'P', 'P', 'R' };
|
||||
char magic[5]{ 'P', 'P', 'P', 'R', 0 };
|
||||
uint16_t version = 0;
|
||||
uint16_t count = 0;
|
||||
};
|
||||
struct item_t {
|
||||
int m_name_len;
|
||||
int m_brush_path_len;
|
||||
int m_brush_thumb_path_len;
|
||||
int m_stencil_path_len;
|
||||
//std::shared_ptr<Texture2D> m_tip_texture;
|
||||
//std::shared_ptr<Texture2D> m_stencil_texture;
|
||||
int m_name_len = 0;
|
||||
int m_brush_path_len = 0;
|
||||
int m_brush_thumb_path_len = 0;
|
||||
int m_stencil_path_len = 0;
|
||||
glm::vec4 m_tip_color{ 0, 0, 0, 1 };
|
||||
float m_tip_size = 0;
|
||||
float m_tip_spacing = 0;
|
||||
@@ -118,7 +129,6 @@ public:
|
||||
virtual void init() override;
|
||||
virtual kEventResult handle_event(Event* e) override;
|
||||
void handle_click(Node* target);
|
||||
std::shared_ptr<Brush> get_brush(int index) const;
|
||||
bool save();
|
||||
bool restore();
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user