#pragma once #include "node.h" #include "node_button_custom.h" #include "node_image.h" #include "node_stroke_preview.h" #include "brush.h" #include "node_scroll.h" class NodeButtonBrush : public NodeButtonCustom { public: 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; NodeImage* img; virtual Node* clone_instantiate() const override; virtual void init() override; void set_icon(const char* path); virtual void draw() override; }; class NodePanelBrush : public Node { // brushes that are marked as deleted but file still exists std::vector 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; bool m_user_brush = false; }; public: std::string m_dir_name; std::function on_brush_changed; std::function on_popup_close; virtual Node* clone_instantiate() const override; virtual void init() override; virtual kEventResult handle_event(Event* e) override; void handle_click(Node* target); int find_brush(const std::string& name) const; std::string get_texture_path(int index) const; std::string get_thumb_path(int index) const; bool save(); bool restore(); }; // ----------------------------------------------------------------------- class NodeBrushPresetItem : public NodeButtonCustom { public: std::shared_ptr m_brush; std::string high_path; std::string thumb_path; bool m_selected = false; NodeStrokePreview* m_preview; NodeImage* m_thumb; virtual Node* clone_instantiate() const override; virtual void init() override; virtual void draw() override; }; class NodePanelBrushPreset : public Node { NodeBrushPresetItem* m_current = nullptr; Node* m_container; NodeButtonCustom* m_btn_add; NodeButtonCustom* m_btn_up; NodeButtonCustom* m_btn_down; NodeButtonCustom* m_btn_delete; NodeButtonCustom* m_btn_save; struct header_t { char magic[5]{ 'P', 'P', 'P', 'R', 0 }; uint16_t version = 0; uint16_t count = 0; }; struct item_t { int m_name_len = 0; int m_brush_path_len = 0; int m_brush_thumb_path_len = 0; int m_dual_path_len = 0; int m_dual_thumb_path_len = 0; int m_stencil_path_len = 0; int m_stencil_thumb_path_len = 0; glm::vec4 m_tip_color{ 0, 0, 0, 1 }; float m_tip_size = 0; float m_tip_spacing = 0; float m_tip_flow = 0; float m_tip_opacity = 0; float m_tip_angle = 0; float m_tip_angle_delay = 0; float m_tip_mix = 0; float m_tip_stencil = 0; float m_tip_wet = 0; float m_tip_noise = 0; float m_tip_hue = 0; float m_tip_sat = 0; float m_tip_val = 0; bool m_tip_angle_follow = false; bool m_tip_flow_pressure = false; bool m_tip_size_pressure = false; float m_jitter_scale = 0; float m_jitter_angle = 0; float m_jitter_spread = 0; float m_jitter_flow = 0; float m_jitter_hue = 0; float m_jitter_sat = 0; float m_jitter_val = 0; int m_blend_mode = 0; bool m_tip_invert = false; bool m_tip_flipx = false; bool m_tip_flipy = false; bool m_tex_enabled = false; bool m_dual_enabled = false; int m_dual_blend_mode = 0; bool m_dual_randflip = false; float m_dual_size = 0; float m_dual_spacing = 0; float m_dual_scatter = 0; bool m_dual_scatter_axis = false; bool m_dual_invert = false; bool m_dual_flipx = false; bool m_dual_flipy = false; bool m_tip_randflipx = false; bool m_tip_randflipy = false; float m_tip_aspect = 0; float m_dual_flow = .75f; float m_dual_opacity = 1.f; float m_dual_rotate = .25f; }; public: std::function& brush)> on_brush_changed; std::function on_popup_close; virtual Node* clone_instantiate() const override; virtual void init() override; virtual kEventResult handle_event(Event* e) override; void handle_click(Node* target); bool save(); bool restore(); void add_brush(std::shared_ptr brush); };