refactor Brush to be used in shared_ptr
This commit is contained in:
@@ -163,7 +163,7 @@
|
||||
<border color=".2" height="20" justify="center" align="center"><text text="Tip Settings" font-face="arial" font-size="11"/></border>
|
||||
<node dir="row">
|
||||
<node width="30%" dir="col">
|
||||
<node height="20" justify="center" margin="5 0 5 0"><text text="Shade" font-face="arial" font-size="11"/></node>
|
||||
<!--<node height="20" justify="center" margin="5 0 5 0"><text text="Shade" font-face="arial" font-size="11"/></node>-->
|
||||
<node height="30" justify="center" margin="5 0 5 0"><text text="Blend" font-face="arial" font-size="11"/></node>
|
||||
<node height="20" justify="center"><text text="Size" font-face="arial" font-size="11"/></node>
|
||||
<node height="20" justify="center"><text text="Flow" font-face="arial" font-size="11"/></node>
|
||||
@@ -179,7 +179,7 @@
|
||||
<node height="20" justify="center"><text text="Val" font-face="arial" font-size="11"/></node>
|
||||
</node>
|
||||
<node dir="col" align="center" grow="1" width="1" flood-events="1">
|
||||
<node height="20" pad="1" width="100%" margin="5 0 5 0"><slider-h id="tip-shade" value="1"/></node>
|
||||
<!--<node height="20" pad="1" width="100%" margin="5 0 5 0"><slider-h id="tip-shade" value="1"/></node>-->
|
||||
<node height="30" pad="1" width="100%" dir="row" margin="5 0 5 0">
|
||||
<combobox id="blend-mode" text="Normal" width="100%" height="30" combo-list="Normal,-,Multiply,Screen,-,Color Dodge,Overlay" default="0"/>
|
||||
</node>
|
||||
|
||||
@@ -128,39 +128,27 @@ void App::init_sidebar()
|
||||
|
||||
// if (canvas)
|
||||
// {
|
||||
// Canvas::I->m_current_brush.m_tip_color = color->m_color;
|
||||
// Canvas::I->m_current_brush->m_tip_color = color->m_color;
|
||||
// stroke->m_canvas->draw_stroke();
|
||||
// }
|
||||
|
||||
//brushes->on_brush_changed = [this](Node* target, int index) {
|
||||
// Canvas::I->m_current_brush.m_tex_id = brushes->get_texture_id(index);
|
||||
// Canvas::I->m_current_brush.id = brushes->get_brush_id(index);
|
||||
// stroke->m_preview->draw_stroke();
|
||||
//};
|
||||
presets->on_brush_changed = [this](Node* target, int index) {
|
||||
auto b = presets->get_brush(index);
|
||||
// don't change some params
|
||||
b.m_tip_size = Canvas::I->m_current_brush.m_tip_size;
|
||||
b.m_tip_color = Canvas::I->m_current_brush.m_tip_color;
|
||||
b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
|
||||
b->m_tip_color = Canvas::I->m_current_brush->m_tip_color;
|
||||
Canvas::I->m_current_brush = b;
|
||||
stroke->m_preview->draw_stroke();
|
||||
};
|
||||
|
||||
color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||
Canvas::I->m_current_brush.m_tip_color = color;
|
||||
Canvas::I->m_current_brush->m_tip_color = color;
|
||||
};
|
||||
//
|
||||
// stroke->on_stroke_change = [this](Node*target) {
|
||||
// if (canvas)
|
||||
// canvas->m_brush = stroke->m_canvas->m_brush;
|
||||
// };
|
||||
stroke->on_brush_changed = [this](Node* target, int brush_id, uint16_t brush_tex) {
|
||||
Canvas::I->m_current_brush.m_tex_id = brush_tex;
|
||||
Canvas::I->m_current_brush.id = brush_id;
|
||||
stroke->on_brush_changed = [this](Node* target, const std::string& path) {
|
||||
Canvas::I->m_current_brush->load_texture(path);
|
||||
stroke->m_preview->draw_stroke();
|
||||
};
|
||||
stroke->on_stencil_changed = [this](Node*target, uint16_t id) {
|
||||
Canvas::I->m_current_brush.m_tex_stencil_id = id;
|
||||
stroke->on_stencil_changed = [this](Node*target, const std::string& path) {
|
||||
Canvas::I->m_current_brush->load_stencil(path);
|
||||
stroke->m_preview->draw_stroke();
|
||||
};
|
||||
|
||||
@@ -263,7 +251,7 @@ void App::init_sidebar()
|
||||
panels->fix_scroll();
|
||||
button->set_color(panels->get_child_index(color.get()) == -1 ? color_button_normal : color_button_hlight);
|
||||
// auto pick = layout[main_id]->add_child<NodeColorPicker>();
|
||||
// pick->m_color_cur->m_color = Canvas::I->m_current_brush.m_tip_color;
|
||||
// pick->m_color_cur->m_color = Canvas::I->m_current_brush->m_tip_color;
|
||||
};
|
||||
}
|
||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-layer"))
|
||||
@@ -395,7 +383,7 @@ void App::init_toolbar_draw()
|
||||
if (auto* button = layout[main_id]->find<NodeButtonCustom>("btn-bucket"))
|
||||
{
|
||||
button->on_click = [this](Node*) {
|
||||
canvas->m_canvas->clear(Canvas::I->m_current_brush.m_tip_color);
|
||||
canvas->m_canvas->clear(Canvas::I->m_current_brush->m_tip_color);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -689,7 +677,7 @@ void App::init_menu_about()
|
||||
|
||||
void App::brush_update()
|
||||
{
|
||||
// brushes->select_brush(canvas->m_brush.id);
|
||||
// brushes->select_brush(canvas->m_brush->id);
|
||||
// stroke->set_params(canvas->m_brush);
|
||||
}
|
||||
|
||||
@@ -826,17 +814,6 @@ void App::initLayout()
|
||||
version_label->set_text(g_version);
|
||||
}
|
||||
|
||||
Brush b;
|
||||
int br_idx = stroke->m_brush_popup->find_brush("Round-Hard");
|
||||
b.m_tex_id = stroke->m_brush_popup->get_texture_id(br_idx);
|
||||
b.id = stroke->m_brush_popup->get_brush_id(br_idx);
|
||||
b.m_tip_size = .1f;
|
||||
b.m_tip_flow = .5f;
|
||||
b.m_tip_spacing = .1f;
|
||||
b.m_tip_opacity = 1.f;
|
||||
Canvas::I->m_current_brush = b;
|
||||
stroke->m_brush_thumb->set_image(stroke->m_brush_popup->get_thumb_path(br_idx));
|
||||
|
||||
brush_update();
|
||||
|
||||
TextureManager::load("data/paper.jpg");
|
||||
|
||||
@@ -65,7 +65,7 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, canvas->m_canvas->m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, canvas->m_canvas->m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_layers[layer_index].m_opacity);
|
||||
//ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[layer_index].m_alpha_locked);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, canvas->m_canvas->m_smask_active);
|
||||
@@ -86,18 +86,18 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
else if (canvas->m_canvas->m_show_tmp && canvas->m_canvas->m_current_layer_idx == layer_index)
|
||||
{
|
||||
sampler.bind(0);
|
||||
auto& paper = TextureManager::get(canvas->m_canvas->m_current_stroke->m_brush.m_tex_stencil_id);
|
||||
auto& paper = *canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture;
|
||||
ShaderManager::use(kShader::CompDraw);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, canvas->m_canvas->m_size);
|
||||
//ShaderManager::u_int(kShaderUniform::TexStencil, 3);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, canvas->m_canvas->m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, canvas->m_canvas->m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_layers[layer_index].m_opacity);
|
||||
ShaderManager::u_int(kShaderUniform::Lock, canvas->m_canvas->m_layers[layer_index].m_alpha_locked);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, canvas->m_canvas->m_smask_active);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, canvas->m_canvas->m_current_stroke->m_brush.m_blend_mode);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, canvas->m_canvas->m_current_stroke->m_brush->m_blend_mode);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
canvas->m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||
@@ -163,25 +163,25 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
{
|
||||
auto pos = mode->m_resizing ? mode->m_size_pos_start : mode->m_cur_pos;
|
||||
if (App::I.keys[(int)kKey::KeyAlt] && !mode->m_resizing)
|
||||
pos.x = pos.x - canvas->m_canvas->m_current_brush.m_tip_size * 500;
|
||||
pos.x = pos.x - canvas->m_canvas->m_current_brush->m_tip_size * 500;
|
||||
auto cur = (glm::vec2(pos.x / width, 1.f - pos.y / height) - 0.5f) * 2.f;
|
||||
|
||||
ShaderManager::use(kShader::StrokePreview);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_current_brush.m_tip_flow);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_canvas->m_current_brush.m_tip_color), 1);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_current_brush->m_tip_flow);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_color), 1);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, tip_color);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP,
|
||||
proj * camera *
|
||||
glm::scale(glm::vec3(100)) *
|
||||
glm::transpose(canvas->m_canvas->m_cam_rot) *
|
||||
glm::translate(glm::vec3(cur * glm::vec2(aspect * tan_fov), -1)) *
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush.m_tip_size * 800.f / App::I.height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush.m_tip_angle * (float)(M_PI * 2.0))
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_size * 800.f / App::I.height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush->m_tip_angle * (float)(M_PI * 2.0))
|
||||
);
|
||||
glEnable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
auto& tex = TextureManager::get(canvas->m_canvas->m_current_brush.m_tex_id);
|
||||
auto& tex = *canvas->m_canvas->m_current_brush->m_tip_texture;
|
||||
tex.bind();
|
||||
sampler_linear.bind(0);
|
||||
m_face_plane.draw_fill();
|
||||
@@ -238,19 +238,19 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
||||
auto pos = glm::translate(glm::normalize(vr_controller_pos));
|
||||
ShaderManager::use(kShader::StrokePreview);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_current_brush.m_tip_flow);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_canvas->m_current_brush.m_tip_color), 1);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, canvas->m_canvas->m_current_brush->m_tip_flow);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_color), 1);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, tip_color);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP,
|
||||
proj * camera * pos *
|
||||
glm::inverse(glm::lookAt({ 0, 0, 0 }, vr_controller_pos, { 0, 1, 0 })) *
|
||||
//glm::scale(glm::vec3(0.1)) *
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush.m_tip_size * 800.f / App::I.height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush.m_tip_angle * (float)(M_PI * 2.0))
|
||||
glm::scale(glm::vec3(canvas->m_canvas->m_current_brush->m_tip_size * 800.f / App::I.height)) *
|
||||
glm::eulerAngleZ(canvas->m_canvas->m_current_brush->m_tip_angle * (float)(M_PI * 2.0))
|
||||
);
|
||||
glEnable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
auto& tex = TextureManager::get(canvas->m_canvas->m_current_brush.m_tex_id);
|
||||
auto& tex = *canvas->m_canvas->m_current_brush->m_tip_texture;
|
||||
tex.bind();
|
||||
sampler_linear.bind(0);
|
||||
m_face_plane.draw_fill();
|
||||
|
||||
@@ -128,6 +128,11 @@ std::string Asset::absolute(const std::string& path)
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Asset::is_asset(const std::string & path)
|
||||
{
|
||||
return path.find("data/") != std::string::npos;
|
||||
}
|
||||
|
||||
bool Asset::open(const char* path)
|
||||
{
|
||||
//LOG("Asset::open %s", path);
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
static bool exist(std::string path, bool is_asset);
|
||||
static bool delete_file(const std::string& path);
|
||||
static std::string absolute(const std::string& path);
|
||||
|
||||
static bool is_asset(const std::string& path);
|
||||
std::string m_current_path;
|
||||
FILE* m_fp = nullptr;
|
||||
int m_len = 0;
|
||||
|
||||
@@ -133,19 +133,19 @@ StrokeSample Stroke::randomize_sample(const glm::vec3& pos, float pressure, floa
|
||||
auto rnd_rad = [&] { return float((double)prng() / (double)prng.max() * M_PI * 2.0); }; // normalized [0, 2pi]
|
||||
auto rnd_vec = [&] { float rad = rnd_rad(); return glm::vec3(cosf(rad), sinf(rad), 0); }; // normalized direction vector
|
||||
|
||||
float size_dyn = m_brush.m_tip_size_pressure ? pressure : 1.f;
|
||||
float flow_dyn = m_brush.m_tip_flow_pressure ? pressure : 1.f;
|
||||
float size_dyn = m_brush->m_tip_size_pressure ? pressure : 1.f;
|
||||
float flow_dyn = m_brush->m_tip_flow_pressure ? pressure : 1.f;
|
||||
|
||||
StrokeSample s;
|
||||
s.origin = pos;
|
||||
s.angle = -curve_angle + (m_brush.m_tip_angle + rnd_nor() * m_brush.m_jitter_angle) * (float)(M_PI * 2.0);
|
||||
s.pos = pos + (rnd_vec() * m_brush.m_jitter_spread * 100.f);
|
||||
s.size = 800.f * m_brush.m_tip_size * (1.f - rnd_nor() * m_brush.m_jitter_scale) * size_dyn;
|
||||
s.flow = m_brush.m_tip_flow * (1.f - rnd_nor() * m_brush.m_jitter_flow) * flow_dyn;
|
||||
auto hsv = convert_rgb2hsv(m_brush.m_tip_color);
|
||||
hsv.x = glm::clamp(glm::mix(hsv.x, (pressure - 0.5f) * 2.0f, m_brush.m_tip_hue * (float)m_brush.m_tip_hue_pressure) + (rnd_nor() - 0.5f) * m_brush.m_jitter_hue, 0.f, 1.f);
|
||||
hsv.y = glm::clamp(glm::mix(hsv.y, (1.f - pressure - 0.5f) * 2.0f, m_brush.m_tip_sat * (float)m_brush.m_tip_sat_pressure) + (rnd_nor() - 0.5f) * m_brush.m_jitter_sat, 0.f, 1.f);
|
||||
hsv.z = glm::clamp(glm::mix(hsv.z, (pressure - 0.5f) * 2.0f, m_brush.m_tip_val * (float)m_brush.m_tip_val_pressure) + (rnd_nor() - 0.5f) * m_brush.m_jitter_val, 0.f, 1.f);
|
||||
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_nor() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
||||
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * 100.f);
|
||||
s.size = 800.f * m_brush->m_tip_size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
||||
s.flow = m_brush->m_tip_flow * (1.f - rnd_nor() * m_brush->m_jitter_flow) * flow_dyn;
|
||||
auto hsv = convert_rgb2hsv(m_brush->m_tip_color);
|
||||
hsv.x = glm::clamp(glm::mix(hsv.x, (pressure - 0.5f) * 2.0f, m_brush->m_tip_hue * (float)m_brush->m_tip_hue_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_hue, 0.f, 1.f);
|
||||
hsv.y = glm::clamp(glm::mix(hsv.y, (1.f - pressure - 0.5f) * 2.0f, m_brush->m_tip_sat * (float)m_brush->m_tip_sat_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_sat, 0.f, 1.f);
|
||||
hsv.z = glm::clamp(glm::mix(hsv.z, (pressure - 0.5f) * 2.0f, m_brush->m_tip_val * (float)m_brush->m_tip_val_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_val, 0.f, 1.f);
|
||||
m_hsv_jitter.add(hsv);
|
||||
s.col = convert_hsv2rgb(m_hsv_jitter.average());
|
||||
return s;
|
||||
@@ -169,7 +169,7 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
||||
float pressure = glm::lerp(A.pressure, B.pressure, t);
|
||||
|
||||
auto s = randomize_sample(pos, pressure, 0);
|
||||
if (m_brush.m_tip_angle_follow)
|
||||
if (m_brush->m_tip_angle_follow)
|
||||
{
|
||||
auto& pre = m_prev_sample;
|
||||
glm::vec2 v = glm::normalize(s.origin - pre.origin);
|
||||
@@ -214,8 +214,8 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
//m_pressure_buff.add(pressure);
|
||||
//pressure = m_pressure_buff.average();
|
||||
|
||||
if (m_brush.m_tip_size_pressure)
|
||||
m_step = glm::max(m_brush.m_tip_spacing * m_brush.m_tip_size * pressure * 800.f, 1.f);
|
||||
if (m_brush->m_tip_size_pressure)
|
||||
m_step = glm::max(m_brush->m_tip_spacing * m_brush->m_tip_size * pressure * 800.f, 1.f);
|
||||
|
||||
float dist = m_keypoints.empty() ? m_step :
|
||||
m_keypoints.back().dist + glm::distance(m_keypoints.back().pos, pos);
|
||||
@@ -229,7 +229,7 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
||||
kp.dist = dist;
|
||||
m_keypoints.push_back(kp);
|
||||
}
|
||||
void Stroke::start(const Brush& brush)
|
||||
void Stroke::start(const std::shared_ptr<Brush>& brush)
|
||||
{
|
||||
m_hold_points.clear();
|
||||
m_curve = 0.f;
|
||||
@@ -238,8 +238,28 @@ void Stroke::start(const Brush& brush)
|
||||
m_hsv_jitter.clear();
|
||||
m_last_kp = 0;
|
||||
m_dist = 0.f;
|
||||
m_brush = brush;
|
||||
m_brush.m_tip_size *= 1.f / glm::tan(glm::radians(m_camera.fov * 0.5f));
|
||||
m_step = glm::max(m_brush.m_tip_spacing * m_brush.m_tip_size * 800.f, 1.f);
|
||||
m_brush = std::make_shared<Brush>(*brush);
|
||||
m_brush->m_tip_size *= 1.f / glm::tan(glm::radians(m_camera.fov * 0.5f));
|
||||
m_step = glm::max(m_brush->m_tip_spacing * m_brush->m_tip_size * 800.f, 1.f);
|
||||
prng.seed(0);
|
||||
}
|
||||
|
||||
bool Brush::load_texture(const std::string & path)
|
||||
{
|
||||
m_tip_texture = std::make_shared<Texture2D>();
|
||||
if (!m_tip_texture->load(path))
|
||||
return false;
|
||||
m_tip_texture->create_mipmaps();
|
||||
m_tip_texture->auto_destroy = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Brush::load_stencil(const std::string & path)
|
||||
{
|
||||
m_stencil_texture = std::make_shared<Texture2D>();
|
||||
if (!m_stencil_texture->load(path))
|
||||
return false;
|
||||
m_stencil_texture->create_mipmaps();
|
||||
m_stencil_texture->auto_destroy = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
15
src/brush.h
15
src/brush.h
@@ -1,14 +1,19 @@
|
||||
#pragma once
|
||||
#include "rtt.h"
|
||||
#include "shader.h"
|
||||
#include "texture.h"
|
||||
|
||||
class Brush
|
||||
{
|
||||
public:
|
||||
Brush() = default;
|
||||
Brush(const Brush& brush) = default;
|
||||
int id = 0;
|
||||
std::string m_name;
|
||||
uint16_t m_tex_id = 0;
|
||||
uint16_t m_tex_stencil_id = const_hash("data/paper.jpg");
|
||||
std::shared_ptr<Texture2D> m_tip_texture;
|
||||
std::shared_ptr<Texture2D> m_stencil_texture;
|
||||
//uint16_t m_tex_id = 0;
|
||||
//uint16_t m_tex_stencil_id = const_hash("data/paper.jpg");
|
||||
glm::vec4 m_tip_color{0, 0, 0, 1};
|
||||
float m_tip_size = 0;
|
||||
float m_tip_spacing = 0;
|
||||
@@ -36,6 +41,8 @@ public:
|
||||
float m_jitter_sat = 0;
|
||||
float m_jitter_val = 0;
|
||||
int m_blend_mode = 0;
|
||||
bool load_texture(const std::string& path);
|
||||
bool load_stencil(const std::string& path);
|
||||
};
|
||||
|
||||
struct StrokeSample
|
||||
@@ -88,7 +95,7 @@ public:
|
||||
float m_dist = 0;
|
||||
float m_step = 0;
|
||||
Camera m_camera;
|
||||
Brush m_brush;
|
||||
std::shared_ptr<Brush> m_brush;
|
||||
cbuffer<float, 3> m_curve_angles;
|
||||
cbuffer<float, 10> m_pressure_buff;
|
||||
cbuffer<glm::vec3, 3> m_hsv_jitter;
|
||||
@@ -98,7 +105,7 @@ public:
|
||||
std::vector<StrokeSample> m_samples;
|
||||
int m_last_kp;
|
||||
std::minstd_rand prng;
|
||||
void start(const Brush& brush);
|
||||
void start(const std::shared_ptr<Brush>& brush);
|
||||
void add_point(glm::vec3 pos, float pressure);
|
||||
void reset(bool clear_keypoints = false);
|
||||
bool has_sample();
|
||||
|
||||
@@ -304,7 +304,7 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
||||
m_sampler.bind(0);
|
||||
m_sampler.bind(1);
|
||||
m_sampler.bind(2);
|
||||
auto& paper = TextureManager::get(m_current_stroke->m_brush.m_tex_stencil_id);
|
||||
auto& paper = *m_current_stroke->m_brush->m_stencil_texture;
|
||||
ShaderManager::use(kShader::CompDraw);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
//ShaderManager::u_int(kShaderUniform::TexA, 0);
|
||||
@@ -312,12 +312,12 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
//ShaderManager::u_vec2(kShaderUniform::Resolution, m_size);
|
||||
//ShaderManager::u_int(kShaderUniform::TexStencil, 3);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, 1);
|
||||
ShaderManager::u_int(kShaderUniform::Lock, m_layers[layer_index].m_alpha_locked);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, m_smask_active);
|
||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush.m_blend_mode);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush->m_blend_mode);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||
@@ -357,10 +357,10 @@ void Canvas::stroke_draw()
|
||||
|
||||
float zoom = m_node->root()->m_zoom;
|
||||
|
||||
auto m_brush = m_current_stroke->m_brush;
|
||||
const auto& m_brush = m_current_stroke->m_brush;
|
||||
auto samples = m_current_stroke->compute_samples();
|
||||
auto& tex = TextureManager::get(m_brush.m_tex_id);
|
||||
auto& stencil = TextureManager::get(m_brush.m_tex_stencil_id);
|
||||
auto& tex = *m_brush->m_tip_texture;
|
||||
auto& stencil = *m_brush->m_stencil_texture;
|
||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||
|
||||
std::vector<vertex_t> B{
|
||||
@@ -396,10 +396,10 @@ void Canvas::stroke_draw()
|
||||
//ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush.m_tip_stencil);
|
||||
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush.m_tip_mix);
|
||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush.m_tip_wet);
|
||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush.m_tip_noise);
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush->m_tip_stencil);
|
||||
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush->m_tip_mix);
|
||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush->m_tip_wet);
|
||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush->m_tip_noise);
|
||||
|
||||
auto unp_vp = zw(m_box);
|
||||
auto unp_inv = glm::inverse(m_proj * m_mv);
|
||||
@@ -443,7 +443,7 @@ void Canvas::stroke_draw()
|
||||
}
|
||||
auto bb_sz = bb_max - bb_min;
|
||||
|
||||
if (m_brush.m_tip_mix > 0.f)
|
||||
if (m_brush->m_tip_mix > 0.f)
|
||||
{
|
||||
stroke_draw_mix(bb_min, bb_sz);
|
||||
|
||||
@@ -569,7 +569,7 @@ void Canvas::stroke_draw()
|
||||
|
||||
ShaderManager::use(kShader::Stroke);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(s.col, m_brush.m_tip_color.a));
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, glm::vec4(s.col, m_brush->m_tip_color.a));
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, s.flow);
|
||||
|
||||
if (P.size() == 4)
|
||||
@@ -827,7 +827,7 @@ void Canvas::stroke_commit()
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, m_smask_active);
|
||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, 1);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
|
||||
@@ -846,18 +846,18 @@ void Canvas::stroke_commit()
|
||||
}
|
||||
else
|
||||
{
|
||||
auto& paper = TextureManager::get(m_current_stroke->m_brush.m_tex_stencil_id);
|
||||
auto& paper = *m_current_stroke->m_brush->m_stencil_texture;
|
||||
|
||||
ShaderManager::use(kShader::CompDraw);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
//ShaderManager::u_vec2(kShaderUniform::Resolution, m_size);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, 1);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, m_smask_active);
|
||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush.m_blend_mode);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_current_stroke->m_brush->m_blend_mode);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
@@ -882,7 +882,7 @@ void Canvas::stroke_commit()
|
||||
// ShaderManager::use(kShader::StrokeLayer);
|
||||
// ShaderManager::u_int(kShaderUniform::TexBG, 1);
|
||||
// ShaderManager::u_int(kShaderUniform::Lock, m_layers[m_current_layer_idx].m_alpha_locked);
|
||||
// ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush.m_tip_opacity);
|
||||
// ShaderManager::u_float(kShaderUniform::Alpha, m_current_stroke->m_brush->m_tip_opacity);
|
||||
//
|
||||
// ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
// ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||
@@ -912,7 +912,7 @@ void Canvas::stroke_update(glm::vec3 point, float pressure)
|
||||
{
|
||||
m_current_stroke->add_point(point, pressure);
|
||||
}
|
||||
void Canvas::stroke_start(glm::vec3 point, float pressure, const Brush& brush)
|
||||
void Canvas::stroke_start(glm::vec3 point, float pressure, const std::shared_ptr<Brush>& brush)
|
||||
{
|
||||
// need to commit this now before starting a new stroke
|
||||
if (m_current_stroke && m_commit_delayed)
|
||||
|
||||
@@ -191,7 +191,7 @@ public:
|
||||
float m_cam_fov = 85;
|
||||
glm::vec2 m_cur_pos;
|
||||
|
||||
Brush m_current_brush;
|
||||
std::shared_ptr<Brush> m_current_brush;
|
||||
|
||||
enum class kCanvasMode { Draw, Erase, Line, Camera, Grid, Transform, Fill, MaskFree, MaskLine, COUNT };
|
||||
kCanvasMode m_state{ kCanvasMode::Draw };
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
void layer_add(std::string name);
|
||||
void layer_order(int idx, int pos);
|
||||
void layer_merge(int source_idx, int dest_idx);
|
||||
void stroke_start(glm::vec3 point, float pressure, const Brush& brush);
|
||||
void stroke_start(glm::vec3 point, float pressure, const std::shared_ptr<Brush>& brush);
|
||||
void stroke_update(glm::vec3 point, float pressure);
|
||||
void stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz);
|
||||
void stroke_draw();
|
||||
|
||||
@@ -120,7 +120,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
m_picking = true;
|
||||
canvas->pick_start();
|
||||
glm::vec4 pix = canvas->pick_get(loc);
|
||||
canvas->m_current_brush.m_tip_color = pix;
|
||||
canvas->m_current_brush->m_tip_color = pix;
|
||||
App::I.color->set_color(pix);
|
||||
}
|
||||
else
|
||||
@@ -140,7 +140,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
{
|
||||
node->mouse_release();
|
||||
glm::vec4 pix = canvas->pick_get(loc);
|
||||
canvas->m_current_brush.m_tip_color = pix;
|
||||
canvas->m_current_brush->m_tip_color = pix;
|
||||
App::I.color->set_color(pix);
|
||||
canvas->pick_end();
|
||||
}
|
||||
@@ -153,7 +153,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
m_resizing = true;
|
||||
m_dragging = true;
|
||||
m_size_pos_start = m_cur_pos;
|
||||
m_size_value_start = canvas->m_current_brush.m_tip_size;
|
||||
m_size_value_start = canvas->m_current_brush->m_tip_size;
|
||||
node->mouse_capture();
|
||||
}
|
||||
break;
|
||||
@@ -171,13 +171,13 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
||||
if (m_dragging && m_picking)
|
||||
{
|
||||
glm::vec4 pix = canvas->pick_get(loc);
|
||||
canvas->m_current_brush.m_tip_color = pix;
|
||||
canvas->m_current_brush->m_tip_color = pix;
|
||||
App::I.color->set_color(pix);
|
||||
}
|
||||
if (m_dragging && m_resizing)
|
||||
{
|
||||
auto diff = m_cur_pos - m_size_pos_start;
|
||||
canvas->m_current_brush.m_tip_size = m_size_value_start + diff.x * 0.001f;
|
||||
canvas->m_current_brush->m_tip_size = m_size_value_start + diff.x * 0.001f;
|
||||
}
|
||||
m_cur_pos = loc;
|
||||
break;
|
||||
@@ -204,14 +204,14 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const
|
||||
{
|
||||
auto pos = m_resizing ? m_size_pos_start : m_cur_pos;
|
||||
if (App::I.keys[(int)kKey::KeyAlt] && !m_resizing)
|
||||
pos.x = pos.x - canvas->m_current_brush.m_tip_size * 500.f;
|
||||
pos.x = pos.x - canvas->m_current_brush->m_tip_size * 500.f;
|
||||
ShaderManager::use(kShader::StrokePreview);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
float tip_scale_fix = 1.f / glm::tan(glm::radians(Canvas::I->m_cam_fov * 0.5f));
|
||||
float tip_scale = canvas->m_current_brush.m_tip_size * 800.f * tip_scale_fix;
|
||||
float tip_angle = canvas->m_current_brush.m_tip_angle * (float)(M_PI * 2.0);
|
||||
float tip_scale = canvas->m_current_brush->m_tip_size * 800.f * tip_scale_fix;
|
||||
float tip_angle = canvas->m_current_brush->m_tip_angle * (float)(M_PI * 2.0);
|
||||
glm::vec2 tip_offset = glm::vec2(0);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_current_brush.m_tip_color), 1);
|
||||
auto tip_color = glm::vec4(glm::vec3(canvas->m_current_brush->m_tip_color), 1);
|
||||
if (canvas->m_current_stroke)
|
||||
{
|
||||
const auto& s = canvas->m_current_stroke->m_prev_sample;
|
||||
@@ -234,7 +234,7 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const
|
||||
bool blend = glIsEnabled(GL_BLEND);
|
||||
glEnable(GL_BLEND);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
auto& tex = TextureManager::get(canvas->m_current_brush.m_tex_id);
|
||||
auto& tex = *canvas->m_current_brush->m_tip_texture;
|
||||
tex.bind();
|
||||
canvas->m_sampler_brush.bind(0);
|
||||
canvas->m_plane.draw_fill();
|
||||
@@ -245,21 +245,20 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const
|
||||
|
||||
void CanvasModePen::leave()
|
||||
{
|
||||
m_brush = canvas->m_current_brush;
|
||||
*m_brush = *canvas->m_current_brush;
|
||||
}
|
||||
|
||||
void CanvasModePen::enter()
|
||||
{
|
||||
m_cur_pos = Canvas::I->m_cur_pos;
|
||||
if (m_valid_brush)
|
||||
if (m_brush)
|
||||
{
|
||||
canvas->m_current_brush = m_brush;
|
||||
*canvas->m_current_brush = *m_brush;
|
||||
App::I.brush_update();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_brush = canvas->m_current_brush;
|
||||
m_valid_brush = true;
|
||||
m_brush = std::make_shared<Brush>(*canvas->m_current_brush);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,7 +305,7 @@ void CanvasModeLine::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, cons
|
||||
{
|
||||
ShaderManager::use(kShader::Color);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, canvas->m_current_brush.m_tip_color);
|
||||
ShaderManager::u_vec4(kShaderUniform::Col, canvas->m_current_brush->m_tip_color);
|
||||
static glm::vec4 AB[2];
|
||||
AB[0] = { m_drag_start, 0, 1 };
|
||||
AB[1] = { m_drag_pos, 0, 1 };
|
||||
|
||||
@@ -62,8 +62,7 @@ class CanvasModePen : public CanvasMode
|
||||
float m_camera_fov;
|
||||
float m_zoom_canvas = 1.f;
|
||||
float m_zoom_start;
|
||||
bool m_valid_brush = false;
|
||||
Brush m_brush;
|
||||
std::shared_ptr<Brush> m_brush;
|
||||
// resizing the tip
|
||||
bool m_resizing = false;
|
||||
public:
|
||||
|
||||
@@ -7,18 +7,25 @@
|
||||
|
||||
bool Image::load(std::string filename)
|
||||
{
|
||||
stbi_set_flip_vertically_on_load(false);
|
||||
Asset file;
|
||||
if (!(file.open(filename.c_str()) && file.read_all()))
|
||||
if (Asset::is_asset(filename))
|
||||
{
|
||||
Asset file;
|
||||
if (!(file.open(filename.c_str()) && file.read_all()))
|
||||
{
|
||||
file.close();
|
||||
return false;
|
||||
}
|
||||
stbi_set_flip_vertically_on_load(false);
|
||||
uint8_t* buffer = stbi_load_from_memory(file.m_data, file.m_len, &width, &height, nullptr, 4);
|
||||
file.close();
|
||||
return false;
|
||||
comp = 4;
|
||||
m_data = std::unique_ptr<uint8_t[]>(buffer);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return load_file(filename);
|
||||
}
|
||||
uint8_t* buffer = stbi_load_from_memory(file.m_data, file.m_len, &width, &height, nullptr, 4);
|
||||
file.close();
|
||||
comp = 4;
|
||||
m_data = std::unique_ptr<uint8_t[]>(buffer);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::load_file(std::string filename)
|
||||
|
||||
@@ -179,7 +179,7 @@ void NodeCanvas::draw()
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_canvas->m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_canvas->m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity);
|
||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||
//ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[layer_index].m_alpha_locked);
|
||||
@@ -201,19 +201,19 @@ void NodeCanvas::draw()
|
||||
else if(m_canvas->m_current_stroke && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
|
||||
{
|
||||
m_sampler.bind(0);
|
||||
auto& paper = TextureManager::get(m_canvas->m_current_stroke->m_brush.m_tex_stencil_id);
|
||||
auto& paper = *m_canvas->m_current_stroke->m_brush->m_stencil_texture;
|
||||
ShaderManager::use(kShader::CompDraw);
|
||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||
ShaderManager::u_int(kShaderUniform::TexMask, 2);
|
||||
//ShaderManager::u_vec2(kShaderUniform::Resolution, zw(m_canvas->m_box) / zoom);
|
||||
//ShaderManager::u_int(kShaderUniform::TexStencil, 3);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_canvas->m_current_stroke->m_brush.m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::StrokeAlpha, m_canvas->m_current_stroke->m_brush->m_tip_opacity);
|
||||
ShaderManager::u_float(kShaderUniform::Alpha, m_canvas->m_layers[layer_index].m_opacity);
|
||||
ShaderManager::u_int(kShaderUniform::Lock, m_canvas->m_layers[layer_index].m_alpha_locked);
|
||||
ShaderManager::u_int(kShaderUniform::Mask, m_canvas->m_smask_active);
|
||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_canvas->m_current_stroke->m_brush.m_blend_mode);
|
||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_canvas->m_current_stroke->m_brush->m_blend_mode);
|
||||
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||
|
||||
@@ -120,6 +120,11 @@ uint16_t NodePanelBrush::get_texture_id(int index) const
|
||||
return m_brushes[index]->high_id;
|
||||
}
|
||||
|
||||
std::string NodePanelBrush::get_texture_path(int index) const
|
||||
{
|
||||
return m_brushes[index]->high_path;
|
||||
}
|
||||
|
||||
std::string NodePanelBrush::get_thumb_path(int index) const
|
||||
{
|
||||
return m_brushes[index]->thumb_path;
|
||||
@@ -201,14 +206,15 @@ void NodePanelBrushPreset::init()
|
||||
brush->thumb_path = path;
|
||||
brush->high_path = path_hi;
|
||||
brush->high_id = const_hash(path_hi.c_str());
|
||||
brush->m_brush.m_tex_id = const_hash(path.c_str());
|
||||
brush->m_brush.m_tip_size = .05;
|
||||
brush->m_brush.m_tip_flow = .2;
|
||||
brush->m_brush.m_tip_opacity = 1;
|
||||
brush->m_brush.m_tip_spacing = 0.03;
|
||||
//brush->m_brush.m_jitter_spread = (rand() % 1000) * 0.0001;
|
||||
brush->m_brush = std::make_shared<Brush>();
|
||||
//brush->m_brush->m_tex_id = const_hash(path.c_str());
|
||||
brush->m_brush->m_tip_size = .05;
|
||||
brush->m_brush->m_tip_flow = .2;
|
||||
brush->m_brush->m_tip_opacity = 1;
|
||||
brush->m_brush->m_tip_spacing = 0.03;
|
||||
//brush->m_brush->m_jitter_spread = (rand() % 1000) * 0.0001;
|
||||
brush->m_preview->m_brush = brush->m_brush;
|
||||
brush->m_preview->draw_stroke();
|
||||
//brush->m_preview->draw_stroke();
|
||||
brush->m_thumb->m_path = path;
|
||||
brush->m_thumb->m_tex_id = const_hash(path.c_str());
|
||||
brush->m_thumb->create();
|
||||
@@ -230,11 +236,11 @@ void NodePanelBrushPreset::handle_click(Node* target)
|
||||
on_brush_changed(this, m_current->m_brushID);
|
||||
}
|
||||
|
||||
Brush NodePanelBrushPreset::get_brush(int index) const
|
||||
std::shared_ptr<Brush> NodePanelBrushPreset::get_brush(int index) const
|
||||
{
|
||||
auto b = m_brushes[index]->m_brush;
|
||||
auto& b = m_brushes[index]->m_brush;
|
||||
TextureManager::load(m_brushes[index]->high_path.c_str(), true);
|
||||
b.m_tex_id = m_brushes[index]->high_id;
|
||||
//b->m_tex_id = m_brushes[index]->high_id;
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -244,6 +250,11 @@ uint16_t NodePanelBrushPreset::get_texture_id(int index) const
|
||||
return m_brushes[index]->high_id;
|
||||
}
|
||||
|
||||
std::string NodePanelBrushPreset::get_texture_path(int index) const
|
||||
{
|
||||
return m_brushes[index]->high_path;
|
||||
}
|
||||
|
||||
int NodePanelBrushPreset::get_brush_id(int index) const
|
||||
{
|
||||
return m_brushes[index]->m_brushID;
|
||||
|
||||
@@ -35,6 +35,7 @@ public:
|
||||
std::vector<std::string> FindAllBrushes(const std::string& folder);
|
||||
int find_brush(const std::string& name) const;
|
||||
uint16_t get_texture_id(int index) const;
|
||||
std::string get_texture_path(int index) const;
|
||||
std::string get_thumb_path(int index) const;
|
||||
int get_brush_id(int index) const;
|
||||
void select_brush(int brush_id);
|
||||
@@ -46,7 +47,7 @@ class NodeBrushPresetItem : public NodeButtonCustom
|
||||
{
|
||||
public:
|
||||
int m_brushID;
|
||||
Brush m_brush;
|
||||
std::shared_ptr<Brush> m_brush;
|
||||
std::string high_path;
|
||||
std::string thumb_path;
|
||||
uint16_t high_id;
|
||||
@@ -69,7 +70,8 @@ public:
|
||||
virtual void init() override;
|
||||
void handle_click(Node* target);
|
||||
uint16_t get_texture_id(int index) const;
|
||||
Brush get_brush(int index) const;
|
||||
std::string get_texture_path(int index) const;
|
||||
std::shared_ptr<Brush> get_brush(int index) const;
|
||||
int get_brush_id(int index) const;
|
||||
};
|
||||
|
||||
|
||||
@@ -55,5 +55,5 @@ void NodePanelColor::set_color(glm::vec3 rgb)
|
||||
|
||||
void NodePanelColor::added(Node* parent)
|
||||
{
|
||||
set_color(Canvas::I->m_current_brush.m_tip_color);
|
||||
set_color(Canvas::I->m_current_brush->m_tip_color);
|
||||
}
|
||||
|
||||
@@ -25,34 +25,75 @@ void NodePanelStroke::init()
|
||||
void NodePanelStroke::update_controls()
|
||||
{
|
||||
const auto& b = Canvas::I->m_current_brush;
|
||||
m_tip_size->m_value.x = glm::pow(b.m_tip_size, 1.f/3.f);
|
||||
m_tip_spacing->m_value.x = glm::pow(b.m_tip_spacing, 1.f/2.f) / 4.f;
|
||||
m_tip_flow->m_value.x = glm::pow(b.m_tip_flow, 1.f/2.f);
|
||||
m_tip_opacity->m_value.x = b.m_tip_opacity;
|
||||
m_tip_angle->m_value.x = b.m_tip_angle;
|
||||
m_tip_stencil->m_value.x = b.m_tip_stencil;
|
||||
m_tip_wet->m_value.x = b.m_tip_wet;
|
||||
m_tip_noise->m_value.x = b.m_tip_noise;
|
||||
m_jitter_scale->m_value.x = b.m_jitter_scale;
|
||||
m_jitter_angle->m_value.x = b.m_jitter_angle;
|
||||
m_jitter_spread->m_value.x = b.m_jitter_spread;
|
||||
m_jitter_flow->m_value.x = b.m_jitter_flow;
|
||||
m_jitter_hue->m_value.x = b.m_jitter_hue;
|
||||
m_jitter_sat->m_value.x = b.m_jitter_sat;
|
||||
m_jitter_val->m_value.x = b.m_jitter_val;
|
||||
m_tip_angle_follow->checked = b.m_tip_angle_follow;
|
||||
m_tip_flow_pressure->checked = b.m_tip_flow_pressure;
|
||||
m_tip_size_pressure->checked = b.m_tip_size_pressure;
|
||||
m_tip_size->m_value.x = glm::pow(b->m_tip_size, 1.f/3.f);
|
||||
m_tip_spacing->m_value.x = glm::pow(b->m_tip_spacing, 1.f/2.f) / 4.f;
|
||||
m_tip_flow->m_value.x = glm::pow(b->m_tip_flow, 1.f/2.f);
|
||||
m_tip_opacity->m_value.x = b->m_tip_opacity;
|
||||
m_tip_angle->m_value.x = b->m_tip_angle;
|
||||
m_tip_stencil->m_value.x = b->m_tip_stencil;
|
||||
m_tip_wet->m_value.x = b->m_tip_wet;
|
||||
m_tip_noise->m_value.x = b->m_tip_noise;
|
||||
m_jitter_scale->m_value.x = b->m_jitter_scale;
|
||||
m_jitter_angle->m_value.x = b->m_jitter_angle;
|
||||
m_jitter_spread->m_value.x = b->m_jitter_spread;
|
||||
m_jitter_flow->m_value.x = b->m_jitter_flow;
|
||||
m_jitter_hue->m_value.x = b->m_jitter_hue;
|
||||
m_jitter_sat->m_value.x = b->m_jitter_sat;
|
||||
m_jitter_val->m_value.x = b->m_jitter_val;
|
||||
m_tip_angle_follow->checked = b->m_tip_angle_follow;
|
||||
m_tip_flow_pressure->checked = b->m_tip_flow_pressure;
|
||||
m_tip_size_pressure->checked = b->m_tip_size_pressure;
|
||||
m_preview->m_brush = b;
|
||||
m_preview->draw_stroke();
|
||||
}
|
||||
|
||||
void NodePanelStroke::init_controls()
|
||||
{
|
||||
m_brush_popup = std::make_shared<NodePanelBrush>();
|
||||
m_brush_popup->m_manager = m_manager;
|
||||
m_brush_popup->init();
|
||||
m_brush_popup->create();
|
||||
m_brush_popup->loaded();
|
||||
m_brush_popup->SetPositioning(YGPositionTypeAbsolute);
|
||||
m_brush_popup->SetSize(400, 400);
|
||||
m_brush_popup->m_mouse_ignore = false;
|
||||
m_brush_popup->m_flood_events = true;
|
||||
m_brush_popup->m_capture_children = false;
|
||||
|
||||
auto b = std::make_shared<Brush>();
|
||||
int br_idx = m_brush_popup->find_brush("Round-Hard");
|
||||
b->load_texture(m_brush_popup->get_texture_path(br_idx));
|
||||
b->load_stencil("data/paper.jpg");
|
||||
b->m_tip_size = .1f;
|
||||
b->m_tip_flow = .5f;
|
||||
b->m_tip_spacing = .1f;
|
||||
b->m_tip_opacity = 1.f;
|
||||
Canvas::I->m_current_brush = b;
|
||||
|
||||
m_brush_thumb = find<NodeImage>("tip-change-thumb");
|
||||
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
|
||||
|
||||
m_brush_button = find<NodeButtonCustom>("tip-change");
|
||||
m_brush_button->on_click = [this](Node*) {
|
||||
glm::vec2 pos = m_brush_button->m_pos + glm::vec2(m_brush_button->m_size.x, 0);
|
||||
root()->add_child(m_brush_popup);
|
||||
m_brush_popup->SetPosition(pos.x, pos.y);
|
||||
m_brush_popup->mouse_capture();
|
||||
root()->update();
|
||||
|
||||
m_brush_popup->on_brush_changed = [this](Node*, int index) {
|
||||
if (on_brush_changed)
|
||||
on_brush_changed(this, m_brush_popup->get_texture_path(index));
|
||||
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(index));
|
||||
m_brush_popup->mouse_release();
|
||||
m_brush_popup->parent->remove_child(m_brush_popup.get());
|
||||
};
|
||||
};
|
||||
|
||||
m_preview = find<NodeStrokePreview>("canvas");
|
||||
m_blend_mode = find<NodeComboBox>("blend-mode");
|
||||
m_blend_mode->on_select = [](Node*, int index) {
|
||||
Canvas::I->m_current_brush.m_blend_mode = index;
|
||||
Canvas::I->m_current_brush->m_blend_mode = index;
|
||||
};
|
||||
|
||||
init_slider(m_tip_size, "tip-size", &Brush::m_tip_size);
|
||||
@@ -91,42 +132,17 @@ void NodePanelStroke::init_controls()
|
||||
auto load_stencil = find<NodeButton>("tip-stencil-load");
|
||||
load_stencil->on_click = [this](Node*) {
|
||||
App::I.pick_image([this](std::string path) {
|
||||
App::I.async_start();
|
||||
if (TextureManager::load(path.c_str()))
|
||||
{
|
||||
if (on_stencil_changed)
|
||||
on_stencil_changed(this, const_hash(path.c_str()));
|
||||
on_stencil_changed(this, path);
|
||||
}
|
||||
App::I.async_redraw();
|
||||
App::I.async_end();
|
||||
});
|
||||
};
|
||||
|
||||
m_brush_popup = std::make_shared<NodePanelBrush>();
|
||||
m_brush_popup->m_manager = m_manager;
|
||||
m_brush_popup->init();
|
||||
m_brush_popup->create();
|
||||
m_brush_popup->loaded();
|
||||
m_brush_popup->SetPositioning(YGPositionTypeAbsolute);
|
||||
m_brush_popup->SetSize(400, 400);
|
||||
m_brush_popup->m_mouse_ignore = false;
|
||||
m_brush_popup->m_flood_events = true;
|
||||
m_brush_popup->m_capture_children = false;
|
||||
|
||||
m_brush_thumb = find<NodeImage>("tip-change-thumb");
|
||||
m_brush_button = find<NodeButtonCustom>("tip-change");
|
||||
m_brush_button->on_click = [this](Node*) {
|
||||
glm::vec2 pos = m_brush_button->m_pos + glm::vec2(m_brush_button->m_size.x, 0);
|
||||
root()->add_child(m_brush_popup);
|
||||
m_brush_popup->SetPosition(pos.x, pos.y);
|
||||
m_brush_popup->mouse_capture();
|
||||
root()->update();
|
||||
|
||||
m_brush_popup->on_brush_changed = [this](Node*, int index) {
|
||||
if (on_brush_changed)
|
||||
on_brush_changed(this, m_brush_popup->get_brush_id(index), m_brush_popup->get_texture_id(index));
|
||||
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(index));
|
||||
m_brush_popup->mouse_release();
|
||||
m_brush_popup->parent->remove_child(m_brush_popup.get());
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
void NodePanelStroke::init_slider(NodeSliderH*& target, const char* id, float Brush::* prop)
|
||||
@@ -134,13 +150,13 @@ void NodePanelStroke::init_slider(NodeSliderH*& target, const char* id, float Br
|
||||
target = find<NodeSliderH>(id);
|
||||
target->on_value_changed = std::bind(&NodePanelStroke::handle_slide,
|
||||
this, prop, std::placeholders::_1, std::placeholders::_2);
|
||||
//m_canvas->m_brush.*prop = target->m_value.x;
|
||||
//m_canvas->m_brush->*prop = target->m_value.x;
|
||||
}
|
||||
|
||||
void NodePanelStroke::handle_slide(float Brush::* prop, Node* target, float value)
|
||||
{
|
||||
auto curve = m_curves.find((NodeSliderH*)target);
|
||||
Canvas::I->m_current_brush.*prop = curve != m_curves.end() ? curve->second(value) : value;
|
||||
Canvas::I->m_current_brush.get()->*prop = curve != m_curves.end() ? curve->second(value) : value;
|
||||
m_preview->m_brush = Canvas::I->m_current_brush;
|
||||
m_preview->draw_stroke();
|
||||
if (on_stroke_change)
|
||||
@@ -152,12 +168,12 @@ void NodePanelStroke::init_checkbox(NodeCheckBox*& target, const char* id, bool
|
||||
target = find<NodeCheckBox>(id);
|
||||
target->on_value_changed = std::bind(&NodePanelStroke::handle_checkbox,
|
||||
this, prop, std::placeholders::_1, std::placeholders::_2);
|
||||
Canvas::I->m_current_brush.*prop = target->checked;
|
||||
Canvas::I->m_current_brush.get()->*prop = target->checked;
|
||||
}
|
||||
|
||||
void NodePanelStroke::handle_checkbox(bool Brush::* prop, Node *target, bool value)
|
||||
{
|
||||
Canvas::I->m_current_brush.*prop = value;
|
||||
Canvas::I->m_current_brush.get()->*prop = value;
|
||||
m_preview->m_brush = Canvas::I->m_current_brush;
|
||||
m_preview->draw_stroke();
|
||||
if (on_stroke_change)
|
||||
|
||||
@@ -43,8 +43,8 @@ public:
|
||||
NodeImage* m_brush_thumb;
|
||||
std::shared_ptr<NodePanelBrush> m_brush_popup;
|
||||
std::function<void(Node* target)> on_stroke_change;
|
||||
std::function<void(Node* target, uint16_t id)> on_stencil_changed;
|
||||
std::function<void(Node* target, int brush_id, uint16_t brush_tex)> on_brush_changed;
|
||||
std::function<void(Node* target, const std::string& path)> on_stencil_changed;
|
||||
std::function<void(Node* target, const std::string& path)> on_brush_changed;
|
||||
std::map<NodeSliderH*, std::function<float(float)>> m_curves;
|
||||
|
||||
virtual Node* clone_instantiate() const override;
|
||||
|
||||
@@ -67,7 +67,7 @@ void NodeStrokePreview::draw_stroke()
|
||||
glEnable(GL_BLEND);
|
||||
glm::mat4 proj = glm::ortho<float>(0, (float)m_rtt.getWidth(), 0, (float)m_rtt.getHeight(), -1, 1);
|
||||
|
||||
auto b = m_brush;
|
||||
const auto& b = m_brush;
|
||||
m_stroke.m_camera.fov = Canvas::I->m_cam_fov;
|
||||
m_stroke.m_camera.rot = Canvas::I->m_cam_rot;
|
||||
m_stroke.reset();
|
||||
@@ -75,12 +75,12 @@ void NodeStrokePreview::draw_stroke()
|
||||
if (!m_stroke.m_keypoints.empty())
|
||||
m_stroke.m_prev_sample.origin = m_stroke.m_keypoints[0].pos;
|
||||
auto samples = m_stroke.compute_samples();
|
||||
auto& tex = TextureManager::get(b.m_tex_id);
|
||||
auto& tex = *b->m_tip_texture;
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
tex.bind();
|
||||
m_sampler_brush.bind(0);
|
||||
|
||||
auto& stencil = TextureManager::get(b.m_tex_stencil_id);
|
||||
auto& stencil = *b->m_stencil_texture;
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
stencil.bind();
|
||||
m_sampler.bind(1);
|
||||
@@ -93,13 +93,13 @@ void NodeStrokePreview::draw_stroke()
|
||||
ShaderManager::u_int(kShaderUniform::TexStencil, 1); // stencil
|
||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_rtt.getWidth(), m_rtt.getHeight() });
|
||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, glm::vec2(0));
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, b.m_tip_stencil);
|
||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, b->m_tip_stencil);
|
||||
m_mesh.draw(samples, proj);
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// ShaderManager::use("stroke");
|
||||
// ShaderManager::u_vec4(kShaderUniform::Col, m_brush.m_tip_color);
|
||||
// ShaderManager::u_vec4(kShaderUniform::Col, m_brush->m_tip_color);
|
||||
// ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||
// for (const auto& s : samples)
|
||||
// {
|
||||
|
||||
@@ -11,7 +11,7 @@ class NodeStrokePreview : public NodeBorder
|
||||
Sampler m_sampler_brush;
|
||||
BrushMesh m_mesh;
|
||||
public:
|
||||
Brush m_brush;
|
||||
std::shared_ptr<Brush> m_brush;
|
||||
Stroke m_stroke;
|
||||
std::vector<glm::vec2> m_bez_points;
|
||||
virtual Node* clone_instantiate() const override;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "log.h"
|
||||
#include "texture.h"
|
||||
#include "util.h"
|
||||
#include "app.h"
|
||||
|
||||
std::map<uint16_t, Texture2D> TextureManager::m_textures;
|
||||
|
||||
@@ -107,6 +108,17 @@ glm::vec2 Texture2D::size() const
|
||||
return { m_width, m_height };
|
||||
}
|
||||
|
||||
Texture2D::~Texture2D()
|
||||
{
|
||||
if (auto_destroy)
|
||||
{
|
||||
LOG("Texture2D auto destroy");
|
||||
App::I.async_start();
|
||||
destroy();
|
||||
App::I.async_end();
|
||||
}
|
||||
}
|
||||
|
||||
bool Sampler::create(GLint filter /*= GL_LINEAR*/, GLint wrap /*= GL_CLAMP_TO_EDGE*/)
|
||||
{
|
||||
#if USE_SAMPLER
|
||||
|
||||
@@ -9,6 +9,7 @@ class Texture2D
|
||||
GLint m_format = 0;
|
||||
GLint m_iformat = 0;
|
||||
public:
|
||||
bool auto_destroy = false;
|
||||
bool has_mips = false;
|
||||
bool create(int width, int height, GLint internal_format = GL_RGBA8, GLint format = GL_RGBA, const uint8_t* data = nullptr);
|
||||
bool create(const Image& img);
|
||||
@@ -22,6 +23,7 @@ public:
|
||||
bool ready() const { return m_tex != 0; }
|
||||
void create_mipmaps();
|
||||
glm::vec2 size() const;
|
||||
~Texture2D();
|
||||
};
|
||||
|
||||
class Sampler
|
||||
|
||||
Reference in New Issue
Block a user