implement add and remove custom brushes

This commit is contained in:
2019-02-02 16:53:33 +01:00
parent e9ead45447
commit d8728344c4
5 changed files with 153 additions and 42 deletions

View File

@@ -126,30 +126,49 @@ void App::initLog()
NSString* docpath = (NSString*)[paths objectAtIndex:0]; NSString* docpath = (NSString*)[paths objectAtIndex:0];
data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding]; data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding];
NSError* err = nil;
NSString* recpath = [docpath stringByAppendingString:@"/rec"]; NSString* recpath = [docpath stringByAppendingString:@"/rec"];
rec_path = [recpath cStringUsingEncoding:NSASCIIStringEncoding]; rec_path = [recpath cStringUsingEncoding:NSASCIIStringEncoding];
NSError* recerr = nil; if (![[NSFileManager defaultManager] createDirectoryAtPath:recpath withIntermediateDirectories:YES attributes:nil error:&err])
if (![[NSFileManager defaultManager] createDirectoryAtPath:recpath withIntermediateDirectories:YES attributes:nil error:&recerr])
{ {
LOG("error creating rec path: %s", [[recerr localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); LOG("error creating rec path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/brushes"] withIntermediateDirectories:YES attributes:nil error:&err])
{
LOG("error creating brushes path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/brushes/thumbs"] withIntermediateDirectories:YES attributes:nil error:&err])
{
LOG("error creating thumbs path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
} }
#elif defined(__OSX__) #elif defined(__OSX__)
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSPicturesDirectory, NSUserDomainMask, YES); NSArray* paths = NSSearchPathForDirectoriesInDomains(NSPicturesDirectory, NSUserDomainMask, YES);
NSString* docpath = [(NSString*)[paths objectAtIndex:0] stringByAppendingString:@"/PanoPainter"]; NSString* docpath = [(NSString*)[paths objectAtIndex:0] stringByAppendingString:@"/PanoPainter"];
NSError* docerr = nil; NSError* err = nil;
if (![[NSFileManager defaultManager] createDirectoryAtPath:docpath withIntermediateDirectories:YES attributes:nil error:&docerr])
if (![[NSFileManager defaultManager] createDirectoryAtPath:docpath withIntermediateDirectories:YES attributes:nil error:&err])
{ {
LOG("error creating rec path: %s", [[docerr localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); LOG("error creating rec path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
} }
data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding]; data_path = [docpath cStringUsingEncoding:NSASCIIStringEncoding];
NSString* recpath = [docpath stringByAppendingString:@"/rec"]; NSString* recpath = [docpath stringByAppendingString:@"/rec"];
rec_path = [recpath cStringUsingEncoding:NSASCIIStringEncoding]; rec_path = [recpath cStringUsingEncoding:NSASCIIStringEncoding];
NSError* recerr = nil; if (![[NSFileManager defaultManager] createDirectoryAtPath:recpath withIntermediateDirectories:YES attributes:nil error:&err])
if (![[NSFileManager defaultManager] createDirectoryAtPath:recpath withIntermediateDirectories:YES attributes:nil error:&recerr])
{ {
LOG("error creating rec path: %s", [[recerr localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]); LOG("error creating rec path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/brushes"] withIntermediateDirectories:YES attributes:nil error:&err])
{
LOG("error creating brushes path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
}
if (![[NSFileManager defaultManager] createDirectoryAtPath:[docpath stringByAppendingString:@"/brushes/thumbs"] withIntermediateDirectories:YES attributes:nil error:&err])
{
LOG("error creating thumbs path: %s", [[err localizedDescription] cStringUsingEncoding:NSASCIIStringEncoding]);
} }
#elif defined(_WIN32) #elif defined(_WIN32)
//CHAR my_documents[MAX_PATH]; //CHAR my_documents[MAX_PATH];
@@ -184,6 +203,12 @@ void App::initLog()
rec_path = data_path + "\\frames"; rec_path = data_path + "\\frames";
if (!PathFileExistsA(rec_path.c_str())) if (!PathFileExistsA(rec_path.c_str()))
CreateDirectoryA(rec_path.c_str(), NULL); CreateDirectoryA(rec_path.c_str(), NULL);
if (!PathFileExistsA((data_path + "\\brushes").c_str()))
CreateDirectoryA((data_path + "\\brushes").c_str(), NULL);
if (!PathFileExistsA((data_path + "\\brushes\\thumbs").c_str()))
CreateDirectoryA((data_path + "\\brushes\\thumbs").c_str(), NULL);
#endif #endif
// TODO: save this path somewhere in the settings, don't overwrite every start // TODO: save this path somewhere in the settings, don't overwrite every start

View File

@@ -39,6 +39,11 @@ bool Image::load_file(std::string filename)
return true; return true;
} }
bool Image::save(const std::string& path)
{
return stbi_write_png(path.c_str(), width, height, comp, data(), 0);
}
void Image::flip() void Image::flip()
{ {
auto flipped = std::make_unique<uint8_t[]>(width*height*4); auto flipped = std::make_unique<uint8_t[]>(width*height*4);

View File

@@ -11,6 +11,7 @@ public:
bool load_file(std::string filename); bool load_file(std::string filename);
const uint8_t* data() const { return m_data.get(); } const uint8_t* data() const { return m_data.get(); }
int size() const { return width * height * comp; } int size() const { return width * height * comp; }
bool save(const std::string& path);
void create(int w, int h) void create(int w, int h)
{ {
width = w; width = w;

View File

@@ -47,10 +47,72 @@ Node* NodePanelBrush::clone_instantiate() const
void NodePanelBrush::init() void NodePanelBrush::init()
{ {
init_template("tpl-panel-brushes"); init_template("tpl-panel-brushes");
//m_layers_container = find<NodeBorder>("layers-container");
static auto icons = Asset::list_files("data/thumbs", true, ".*\\.png$"); static auto icons = Asset::list_files("data/thumbs", true, ".*\\.png$");
if ((m_container = find<NodeBorder>("brushes"))) m_btn_add = find<NodeButtonCustom>("btn-add");
m_btn_add->on_click = [this](Node*) {
App::I.pick_image([this](std::string path) {
Image img;
if (img.load_file(path))
{
std::string name, base, ext;
std::regex r(R"((.*)[\\/]([^\\/]+)\.(\w+)$)");
std::smatch m;
if (std::regex_search(path, m, r))
{
base = m[1].str();
name = m[2].str();
ext = m[3].str();
std::string path_high = App::I.data_path + "/brushes/" + name + ".png";
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
auto thumb = img.resize(64, 64);
thumb.save(path_thumb);
img.save(path_high);
async_start();
NodeButtonBrush* brush = new NodeButtonBrush;
m_container->add_child(brush);
brush->init();
brush->create();
brush->loaded();
brush->set_icon(path.c_str());
brush->thumb_path = path_thumb;
brush->high_path = path_high;
brush->brush_name = name;
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
app_redraw();
async_end();
}
}
});
};
m_btn_remove = find<NodeButtonCustom>("btn-remove");
m_btn_remove->on_click = [this](Node*) {
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);
m_container->remove_child(m_current);
if (m_container->m_children.size() > 0)
{
idx = std::max(0, std::min(idx, (int)m_container->m_children.size() - 1));
m_current = (NodeButtonBrush*)m_container->m_children[idx].get();
m_current->m_selected = true;
if (on_brush_changed)
on_brush_changed(this, idx);
}
else
{
m_current = nullptr;
}
}
};
if ((m_container = find<NodeScroll>("brushes")))
{ {
int count = 0; int count = 0;
for (auto& i : icons) for (auto& i : icons)
@@ -63,12 +125,26 @@ void NodePanelBrush::init()
brush->create(); brush->create();
brush->loaded(); brush->loaded();
brush->set_icon(path.c_str()); brush->set_icon(path.c_str());
brush->m_brushID = count++;
brush->thumb_path = path; brush->thumb_path = path;
brush->high_path = path_hi; brush->high_path = path_hi;
brush->brush_name = i; brush->brush_name = i;
brush->high_id = const_hash(path_hi.c_str()); brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
m_brushes.push_back(brush); }
auto custom_icons = Asset::list_files(App::I.data_path + "/brushes", true, ".*\\.png$");
for (auto& i : custom_icons)
{
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + i;
std::string path_high = App::I.data_path + "/brushes/" + i;
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 = i;
brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1); brush->on_click = std::bind(&NodePanelBrush::handle_click, this, std::placeholders::_1);
} }
} }
@@ -103,46 +179,45 @@ void NodePanelBrush::handle_click(Node* target)
m_current = (NodeButtonBrush*)target; m_current = (NodeButtonBrush*)target;
m_current->m_selected = true; m_current->m_selected = true;
if (on_brush_changed) if (on_brush_changed)
on_brush_changed(this, m_current->m_brushID); on_brush_changed(this, m_container->get_child_index(target));
} }
int NodePanelBrush::find_brush(const std::string & name) const int NodePanelBrush::find_brush(const std::string & name) const
{ {
for (int i = 0; i < m_brushes.size(); i++) for (int i = 0; i < m_container->m_children.size(); i++)
{
if (m_brushes[i]->brush_name.find(name) != std::string::npos)
{ {
NodeButtonBrush* b = (NodeButtonBrush*)m_container->m_children[i].get();
if (b->brush_name.find(name) != std::string::npos)
return i; return i;
} }
}
return -1; return -1;
} }
std::string NodePanelBrush::get_texture_path(int index) const std::string NodePanelBrush::get_texture_path(int index) const
{ {
return m_brushes[index]->high_path; return ((NodeButtonBrush*)m_container->m_children[index].get())->high_path;
} }
std::string NodePanelBrush::get_thumb_path(int index) const std::string NodePanelBrush::get_thumb_path(int index) const
{ {
return m_brushes[index]->thumb_path; return ((NodeButtonBrush*)m_container->m_children[index].get())->thumb_path;
} }
// select the current brush based on the texture id // select the current brush based on the texture id
void NodePanelBrush::select_brush(int brush_id) //void NodePanelBrush::select_brush(int brush_id)
{ //{
if (m_current) // if (m_current)
m_current->m_selected = false; // m_current->m_selected = false;
for (auto b : m_brushes) // for (auto b : m_brushes)
{ // {
if (b->m_brushID == brush_id) // if (b->m_brushID == brush_id)
{ // {
b->m_selected = true; // b->m_selected = true;
m_current = b; // m_current = b;
TextureManager::load(b->high_path.c_str(), true); // TextureManager::load(b->high_path.c_str(), true);
} // }
} // }
} //}
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------

View File

@@ -4,16 +4,17 @@
#include "node_image.h" #include "node_image.h"
#include "node_stroke_preview.h" #include "node_stroke_preview.h"
#include "brush.h" #include "brush.h"
#include "node_scroll.h"
class NodeButtonBrush : public NodeButtonCustom class NodeButtonBrush : public NodeButtonCustom
{ {
public: public:
int m_brushID; //int m_brushID;
bool m_selected = false; bool m_selected = false;
std::string brush_name; std::string brush_name;
std::string high_path; std::string high_path;
std::string thumb_path; std::string thumb_path;
uint16_t high_id; //uint16_t high_id;
NodeImage* img; NodeImage* img;
virtual Node* clone_instantiate() const override; virtual Node* clone_instantiate() const override;
virtual void init() override; virtual void init() override;
@@ -23,11 +24,15 @@ public:
class NodePanelBrush : public Node class NodePanelBrush : public Node
{ {
std::vector<NodeButtonBrush*> m_brushes; //std::vector<NodeButtonBrush*> m_brushes;
NodeButtonBrush* m_current = nullptr; NodeButtonBrush* m_current = nullptr;
Node* m_container; NodeScroll* m_container;
NodeButtonCustom* m_btn_add;
NodeButtonCustom* m_btn_up;
NodeButtonCustom* m_btn_down;
NodeButtonCustom* m_btn_remove;
public: public:
std::function<void(Node* target, int id)> on_brush_changed; std::function<void(Node* target, int index)> on_brush_changed;
std::function<void(Node* target)> on_popup_close; std::function<void(Node* target)> on_popup_close;
virtual Node* clone_instantiate() const override; virtual Node* clone_instantiate() const override;
virtual void init() override; virtual void init() override;
@@ -36,7 +41,7 @@ public:
int find_brush(const std::string& name) const; int find_brush(const std::string& name) const;
std::string get_texture_path(int index) const; std::string get_texture_path(int index) const;
std::string get_thumb_path(int index) const; std::string get_thumb_path(int index) const;
void select_brush(int brush_id); //void select_brush(int brush_id);
}; };
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------