enable rtt dtor, default values for <text> node, dual-brush wip, more brush options
This commit is contained in:
726
data/layout.xml
726
data/layout.xml
File diff suppressed because it is too large
Load Diff
@@ -112,7 +112,7 @@ std::vector<std::shared_ptr<Brush>> ABR::compute_brushes(const std::string& path
|
|||||||
auto b = std::make_shared<Brush>();
|
auto b = std::make_shared<Brush>();
|
||||||
b->m_name = wstr2str(p->value<String>("Nm "));
|
b->m_name = wstr2str(p->value<String>("Nm "));
|
||||||
//b->m_tip_color = i.m_tip_color;
|
//b->m_tip_color = i.m_tip_color;
|
||||||
b->m_tip_size = samp->value<UnitFloat>("Dmtr") / (800.f * 4.f);
|
b->m_tip_size = samp->value<UnitFloat>("Dmtr") / 800.f;
|
||||||
b->m_tip_spacing = samp->value<UnitFloat>("Spcn") * 0.01f;
|
b->m_tip_spacing = samp->value<UnitFloat>("Spcn") * 0.01f;
|
||||||
b->m_tip_flow = .25f;
|
b->m_tip_flow = .25f;
|
||||||
b->m_tip_opacity = 1.f;
|
b->m_tip_opacity = 1.f;
|
||||||
|
|||||||
@@ -664,7 +664,7 @@ void App::init_menu_about()
|
|||||||
b->on_click = [this, popup](Node*) {
|
b->on_click = [this, popup](Node*) {
|
||||||
LOG("perf");
|
LOG("perf");
|
||||||
auto start = std::chrono::high_resolution_clock::now();
|
auto start = std::chrono::high_resolution_clock::now();
|
||||||
Canvas::I->stroke_start({ 0, 0, 0 }, 0.9f, Canvas::I->m_current_brush);
|
Canvas::I->stroke_start({ 0, 0, 0 }, 0.9f);
|
||||||
for (int i = 0; i < 100; i++)
|
for (int i = 0; i < 100; i++)
|
||||||
{
|
{
|
||||||
Canvas::I->stroke_update({ 100, 100, 0 }, 0.9f);
|
Canvas::I->stroke_update({ 100, 100, 0 }, 0.9f);
|
||||||
|
|||||||
@@ -218,7 +218,7 @@ void App::initShaders()
|
|||||||
"uniform bool lock;\n"
|
"uniform bool lock;\n"
|
||||||
"uniform bool mask;\n"
|
"uniform bool mask;\n"
|
||||||
"uniform bool fragUV2;\n"
|
"uniform bool fragUV2;\n"
|
||||||
"uniform bool useDual;\n"
|
"uniform bool use_dual;\n"
|
||||||
"in mediump vec2 uv;\n"
|
"in mediump vec2 uv;\n"
|
||||||
"out mediump vec4 frag;\n"
|
"out mediump vec4 frag;\n"
|
||||||
SHADER_FUNCTION_BLUR
|
SHADER_FUNCTION_BLUR
|
||||||
@@ -227,6 +227,9 @@ void App::initShaders()
|
|||||||
" mediump vec2 uv2 = fragUV2 ? (gl_FragCoord.st / resolution) : uv;\n"
|
" mediump vec2 uv2 = fragUV2 ? (gl_FragCoord.st / resolution) : uv;\n"
|
||||||
" mediump vec4 base = texture(tex, uv2);\n"
|
" mediump vec4 base = texture(tex, uv2);\n"
|
||||||
" mediump vec4 stroke = texture(tex_stroke, uv);\n"
|
" mediump vec4 stroke = texture(tex_stroke, uv);\n"
|
||||||
|
" mediump vec4 dual = texture(tex_dual, uv);\n"
|
||||||
|
" if (use_dual)\n"
|
||||||
|
" stroke.a = stroke.a * dual.a;\n"
|
||||||
" stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv2).r : stroke.a * stroke_alpha;\n"
|
" stroke.a = mask ? stroke.a * stroke_alpha * blur(tex_mask, uv2).r : stroke.a * stroke_alpha;\n"
|
||||||
" if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; }\n"
|
" if (!lock && base.a == 0.0) { frag = stroke * vec4(1.0, 1.0, 1.0, alpha); return; }\n"
|
||||||
" mediump vec4 blended = blend(base, stroke, blend_mode);\n"
|
" mediump vec4 blended = blend(base, stroke, blend_mode);\n"
|
||||||
|
|||||||
@@ -132,21 +132,28 @@ StrokeSample Stroke::randomize_sample(const glm::vec3& pos, float pressure, floa
|
|||||||
auto rnd_neg = [&] { return float((double)prng() / (double)prng.max() * 2.0 - 1.0); }; // normalized [-1, +1]
|
auto rnd_neg = [&] { return float((double)prng() / (double)prng.max() * 2.0 - 1.0); }; // normalized [-1, +1]
|
||||||
auto rnd_rad = [&] { return float((double)prng() / (double)prng.max() * M_PI * 2.0); }; // normalized [0, 2pi]
|
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
|
auto rnd_vec = [&] { float rad = rnd_rad(); return glm::vec3(cosf(rad), sinf(rad), 0); }; // normalized direction vector
|
||||||
|
auto rnd_bneg = [&] { return prng() % 2 == 0 ? -1.f : 1.f; }; // -1 or 1
|
||||||
|
|
||||||
float size_dyn = m_brush->m_tip_size_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;
|
float flow_dyn = m_brush->m_tip_flow_pressure ? pressure : 1.f;
|
||||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||||
|
float randflipx = m_brush->m_tip_randflipx ? rnd_bneg() : 1.f;
|
||||||
|
float randflipy = m_brush->m_tip_randflipy ? rnd_bneg() : 1.f;
|
||||||
|
|
||||||
StrokeSample s;
|
StrokeSample s;
|
||||||
|
s.scale.x = randflipx * (m_brush->m_tip_flipx ? -1.f : 1.f) *
|
||||||
|
(m_brush->m_tip_aspect <= 0.5 ? m_brush->m_tip_aspect * 2.f : 1.f);
|
||||||
|
s.scale.y = randflipy * (m_brush->m_tip_flipy ? -1.f : 1.f) *
|
||||||
|
(m_brush->m_tip_aspect > 0.5 ? 1.f - (m_brush->m_tip_aspect - .5f) * 2.f : 1.f);
|
||||||
s.origin = pos;
|
s.origin = pos;
|
||||||
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_neg() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_neg() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
||||||
s.size = 800.f * size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
s.size = 800.f * size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
||||||
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * s.size);
|
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * s.size);
|
||||||
s.flow = m_brush->m_tip_flow * (1.f - rnd_nor() * m_brush->m_jitter_flow) * flow_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);
|
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.x = glm::clamp(glm::mix(hsv.x, (pressure - 0.5f) * 2.0f, m_brush->m_tip_hue) + (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.y = glm::clamp(glm::mix(hsv.y, (1.f - pressure - 0.5f) * 2.0f, m_brush->m_tip_sat) + (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);
|
hsv.z = glm::clamp(glm::mix(hsv.z, (pressure - 0.5f) * 2.0f, m_brush->m_tip_val) + (rnd_nor() - 0.5f) * m_brush->m_jitter_val, 0.f, 1.f);
|
||||||
m_hsv_jitter.add(hsv);
|
m_hsv_jitter.add(hsv);
|
||||||
s.col = convert_hsv2rgb(m_hsv_jitter.average());
|
s.col = convert_hsv2rgb(m_hsv_jitter.average());
|
||||||
return s;
|
return s;
|
||||||
@@ -159,13 +166,13 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
|||||||
samples.reserve(nsamples); // preallocate the estimate number of samples
|
samples.reserve(nsamples); // preallocate the estimate number of samples
|
||||||
while (m_keypoints.back().dist > (m_dist + m_step))
|
while (m_keypoints.back().dist > (m_dist + m_step))
|
||||||
{
|
{
|
||||||
bool is_first = m_last_kp == 0;
|
|
||||||
m_dist += m_step;
|
m_dist += m_step;
|
||||||
m_dir_dist += m_step;
|
m_dir_dist += m_step;
|
||||||
|
int old_kp = m_last_kp;
|
||||||
while (m_dist > m_keypoints[m_last_kp + 1].dist)
|
while (m_dist > m_keypoints[m_last_kp + 1].dist)
|
||||||
m_last_kp++;
|
m_last_kp++;
|
||||||
const auto& A = m_keypoints[m_last_kp];
|
const auto& A = m_keypoints[old_kp];
|
||||||
const auto& B = m_keypoints[m_last_kp + 1]; // NOTE: this should be true when while is true
|
const auto& B = m_keypoints[m_last_kp == old_kp ? m_last_kp + 1 : m_last_kp]; // NOTE: this should be true when while is true
|
||||||
float t = (m_dist - A.dist) / (B.dist - A.dist); // NOTE: must be A != B
|
float t = (m_dist - A.dist) / (B.dist - A.dist); // NOTE: must be A != B
|
||||||
auto pos = glm::lerp(A.pos, B.pos, t);
|
auto pos = glm::lerp(A.pos, B.pos, t);
|
||||||
float pressure = glm::lerp(A.pressure, B.pressure, t);
|
float pressure = glm::lerp(A.pressure, B.pressure, t);
|
||||||
@@ -175,16 +182,20 @@ std::vector<StrokeSample> Stroke::compute_samples()
|
|||||||
{
|
{
|
||||||
if (m_brush->m_tip_angle_follow)
|
if (m_brush->m_tip_angle_follow)
|
||||||
{
|
{
|
||||||
if (m_dir_dist > m_dir_step)
|
if (m_dir_dist > m_dir_step && m_last_kp != m_dir_kp)
|
||||||
{
|
{
|
||||||
glm::vec2 v = glm::normalize(m_keypoints[m_last_kp].pos - m_keypoints[m_dir_kp].pos);
|
glm::vec2 v = glm::normalize(m_keypoints[m_last_kp].pos - m_keypoints[m_dir_kp].pos);
|
||||||
m_dir_angle = -glm::orientedAngle(v, m_dir_ref);
|
m_dir_angle = -glm::orientedAngle(v, m_dir_ref);
|
||||||
if (glm::abs(m_dir_angle) > glm::pi<float>() / 2.f || !m_dir_valid)
|
if (m_brush->m_tip_angle_delay > 0 && (glm::abs(m_dir_angle) > glm::pi<float>() / 2.f || !m_dir_valid))
|
||||||
{
|
{
|
||||||
m_direction.clear();
|
auto old_dir = m_dir_ref;
|
||||||
m_dir_ref = v;
|
m_dir_ref = v;
|
||||||
m_dir_ref_angle = -glm::orientedAngle(m_dir_ref, { 1, 0 });
|
m_dir_ref_angle = -glm::orientedAngle(m_dir_ref, { 1, 0 });
|
||||||
m_dir_angle = 0;
|
m_dir_angle = 0;
|
||||||
|
//m_direction.clear();
|
||||||
|
auto angle_diff = -glm::orientedAngle(m_dir_ref, old_dir);
|
||||||
|
for (int i = 0; i < m_direction.m_count; i++)
|
||||||
|
m_direction.m_vec[i] -= angle_diff;
|
||||||
}
|
}
|
||||||
m_dir_kp = m_last_kp;
|
m_dir_kp = m_last_kp;
|
||||||
m_dir_dist = 0;
|
m_dir_dist = 0;
|
||||||
@@ -245,7 +256,7 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
|||||||
if (m_brush->m_tip_size_pressure)
|
if (m_brush->m_tip_size_pressure)
|
||||||
{
|
{
|
||||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||||
m_step = glm::max(m_brush->m_tip_spacing * size * pressure * 800.f, 1.f);
|
m_step = glm::max(m_brush->m_tip_spacing * size * pressure * 800.f, 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
float dist = m_keypoints.empty() ? m_step :
|
float dist = m_keypoints.empty() ? m_step :
|
||||||
@@ -276,6 +287,7 @@ void Stroke::start(const std::shared_ptr<Brush>& brush)
|
|||||||
m_brush = brush;
|
m_brush = brush;
|
||||||
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
float size = glm::min(m_brush->m_tip_size / glm::tan(glm::radians(m_camera.fov * 0.5f)), m_max_size);
|
||||||
m_step = glm::max(m_brush->m_tip_spacing * size * 800.f, 1.f);
|
m_step = glm::max(m_brush->m_tip_spacing * size * 800.f, 1.f);
|
||||||
|
m_direction.resize(std::max<int>(1, m_brush->m_tip_angle_delay * 200.f / m_step));
|
||||||
prng.seed(0);
|
prng.seed(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,6 +303,18 @@ bool Brush::load_texture(const std::string& path, const std::string& thumb)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Brush::load_dual(const std::string& path, const std::string& thumb)
|
||||||
|
{
|
||||||
|
m_dual_texture = std::make_shared<Texture2D>();
|
||||||
|
if (!m_dual_texture->load(path))
|
||||||
|
return false;
|
||||||
|
m_dual_texture->create_mipmaps();
|
||||||
|
m_dual_texture->auto_destroy = true;
|
||||||
|
m_dual_path = path;
|
||||||
|
m_dual_thumb_path = thumb;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Brush::load_stencil(const std::string& path)
|
bool Brush::load_stencil(const std::string& path)
|
||||||
{
|
{
|
||||||
m_stencil_texture = std::make_shared<Texture2D>();
|
m_stencil_texture = std::make_shared<Texture2D>();
|
||||||
@@ -316,6 +340,19 @@ bool Brush::load()
|
|||||||
m_tip_texture->create_mipmaps();
|
m_tip_texture->create_mipmaps();
|
||||||
m_tip_texture->auto_destroy = true;
|
m_tip_texture->auto_destroy = true;
|
||||||
}
|
}
|
||||||
|
if (!m_dual_path.empty())
|
||||||
|
{
|
||||||
|
m_dual_texture = std::make_shared<Texture2D>();
|
||||||
|
if (!m_dual_texture->load(m_dual_path))
|
||||||
|
{
|
||||||
|
LOG("failed to load %s", m_dual_path.c_str());
|
||||||
|
m_tip_texture = nullptr;
|
||||||
|
m_dual_texture = nullptr;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_dual_texture->create_mipmaps();
|
||||||
|
m_dual_texture->auto_destroy = true;
|
||||||
|
}
|
||||||
if (!m_stencil_path.empty())
|
if (!m_stencil_path.empty())
|
||||||
{
|
{
|
||||||
m_stencil_texture = std::make_shared<Texture2D>();
|
m_stencil_texture = std::make_shared<Texture2D>();
|
||||||
@@ -323,6 +360,7 @@ bool Brush::load()
|
|||||||
{
|
{
|
||||||
LOG("failed to load %s", m_stencil_path.c_str());
|
LOG("failed to load %s", m_stencil_path.c_str());
|
||||||
m_tip_texture = nullptr;
|
m_tip_texture = nullptr;
|
||||||
|
m_dual_texture = nullptr;
|
||||||
m_stencil_texture = nullptr;
|
m_stencil_texture = nullptr;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/brush.h
49
src/brush.h
@@ -6,22 +6,29 @@
|
|||||||
class Brush
|
class Brush
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Brush() = default;
|
//Brush() = default;
|
||||||
Brush(const Brush& brush) = default;
|
//Brush(const Brush& brush) = default;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
|
std::shared_ptr<Texture2D> m_tip_texture;
|
||||||
std::string m_brush_path;
|
std::string m_brush_path;
|
||||||
std::string m_brush_thumb_path;
|
std::string m_brush_thumb_path;
|
||||||
std::string m_stencil_path;
|
|
||||||
std::shared_ptr<Texture2D> m_tip_texture;
|
std::shared_ptr<Texture2D> m_dual_texture;
|
||||||
|
std::string m_dual_path;
|
||||||
|
std::string m_dual_thumb_path;
|
||||||
|
|
||||||
std::shared_ptr<Texture2D> m_stencil_texture;
|
std::shared_ptr<Texture2D> m_stencil_texture;
|
||||||
//uint16_t m_tex_id = 0;
|
std::string m_stencil_path;
|
||||||
//uint16_t m_tex_stencil_id = const_hash("data/paper.jpg");
|
std::string m_stencil_thumb_path;
|
||||||
|
|
||||||
glm::vec4 m_tip_color{0, 0, 0, 1};
|
glm::vec4 m_tip_color{0, 0, 0, 1};
|
||||||
float m_tip_size = 0;
|
float m_tip_size = 0;
|
||||||
float m_tip_spacing = 0;
|
float m_tip_spacing = 0;
|
||||||
float m_tip_flow = 0;
|
float m_tip_flow = 0;
|
||||||
float m_tip_opacity = 0;
|
float m_tip_opacity = 0;
|
||||||
float m_tip_angle = 0;
|
float m_tip_angle = 0;
|
||||||
|
float m_tip_angle_delay = 0;
|
||||||
float m_tip_mix = 0;
|
float m_tip_mix = 0;
|
||||||
float m_tip_stencil = 0;
|
float m_tip_stencil = 0;
|
||||||
float m_tip_wet = 0;
|
float m_tip_wet = 0;
|
||||||
@@ -32,9 +39,6 @@ public:
|
|||||||
bool m_tip_angle_follow = false;
|
bool m_tip_angle_follow = false;
|
||||||
bool m_tip_flow_pressure = false;
|
bool m_tip_flow_pressure = false;
|
||||||
bool m_tip_size_pressure = false;
|
bool m_tip_size_pressure = false;
|
||||||
bool m_tip_hue_pressure = false;
|
|
||||||
bool m_tip_sat_pressure = false;
|
|
||||||
bool m_tip_val_pressure = false;
|
|
||||||
float m_jitter_scale = 0;
|
float m_jitter_scale = 0;
|
||||||
float m_jitter_angle = 0;
|
float m_jitter_angle = 0;
|
||||||
float m_jitter_spread = 0;
|
float m_jitter_spread = 0;
|
||||||
@@ -43,7 +47,27 @@ public:
|
|||||||
float m_jitter_sat = 0;
|
float m_jitter_sat = 0;
|
||||||
float m_jitter_val = 0;
|
float m_jitter_val = 0;
|
||||||
int m_blend_mode = 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.5;
|
||||||
|
|
||||||
bool load_texture(const std::string& path, const std::string& thumb);
|
bool load_texture(const std::string& path, const std::string& thumb);
|
||||||
|
bool load_dual(const std::string& path, const std::string& thumb);
|
||||||
bool load_stencil(const std::string& path);
|
bool load_stencil(const std::string& path);
|
||||||
bool load();
|
bool load();
|
||||||
};
|
};
|
||||||
@@ -53,6 +77,7 @@ struct StrokeSample
|
|||||||
glm::vec3 col = { 0, 0, 0 };
|
glm::vec3 col = { 0, 0, 0 };
|
||||||
glm::vec3 pos = { 0, 0, 0 };
|
glm::vec3 pos = { 0, 0, 0 };
|
||||||
glm::vec3 origin = { 0, 0, 0 };
|
glm::vec3 origin = { 0, 0, 0 };
|
||||||
|
glm::vec2 scale = { 1, 1 };
|
||||||
float size = 0;
|
float size = 0;
|
||||||
float flow = 0;
|
float flow = 0;
|
||||||
float angle = 0;
|
float angle = 0;
|
||||||
@@ -110,9 +135,9 @@ public:
|
|||||||
bool m_filter_points = true;
|
bool m_filter_points = true;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
std::shared_ptr<Brush> m_brush;
|
std::shared_ptr<Brush> m_brush;
|
||||||
cbuffer<float, 3> m_direction;
|
cbuffer<float> m_direction{ 1 };
|
||||||
cbuffer<float, 10> m_pressure_buff;
|
cbuffer<float> m_pressure_buff{ 10 };
|
||||||
cbuffer<glm::vec3, 3> m_hsv_jitter;
|
cbuffer<glm::vec3> m_hsv_jitter{ 3 };
|
||||||
StrokeSample m_prev_sample;
|
StrokeSample m_prev_sample;
|
||||||
std::vector<Keypoint> m_keypoints;
|
std::vector<Keypoint> m_keypoints;
|
||||||
std::vector<std::pair<glm::vec3, float>> m_hold_points;
|
std::vector<std::pair<glm::vec3, float>> m_hold_points;
|
||||||
|
|||||||
164
src/canvas.cpp
164
src/canvas.cpp
@@ -252,6 +252,7 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
|||||||
ShaderManager::u_int(kShaderUniform::Lock, false/*m_layers[layer_index].m_alpha_locked*/);
|
ShaderManager::u_int(kShaderUniform::Lock, false/*m_layers[layer_index].m_alpha_locked*/);
|
||||||
ShaderManager::u_int(kShaderUniform::Mask, false/*m_smask_active*/);
|
ShaderManager::u_int(kShaderUniform::Mask, false/*m_smask_active*/);
|
||||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
||||||
|
ShaderManager::u_int(kShaderUniform::UseDual, 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);
|
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
@@ -273,11 +274,11 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
|||||||
gl.restore();
|
gl.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B)
|
std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vertex_t, 4>& B) const
|
||||||
{
|
{
|
||||||
// intersect P with the current face to clip diverging points from the plane
|
// intersect P with the current face to clip diverging points from the plane
|
||||||
auto unp_vp = zw(m_box);
|
const auto unp_vp = zw(m_box);
|
||||||
auto unp_inv = glm::inverse(m_proj * m_mv);
|
const auto unp_inv = glm::inverse(m_proj * m_mv);
|
||||||
std::array<std::vector<vertex_t>, 6> ret;
|
std::array<std::vector<vertex_t>, 6> ret;
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
@@ -338,7 +339,7 @@ std::array<std::vector<vertex_t>, 6> Canvas::stroke_draw_project(std::array<vert
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
glm::vec4 Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
||||||
{
|
{
|
||||||
if (!ShaderManager::ext_framebuffer_fetch)
|
if (!ShaderManager::ext_framebuffer_fetch)
|
||||||
{
|
{
|
||||||
@@ -364,9 +365,6 @@ void Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
|||||||
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
tex_pos.x, tex_pos.y, tex_sz.x, tex_sz.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_dirty_box[i] = glm::vec4(glm::min(xy(m_dirty_box[i]), (glm::vec2)tex_pos),
|
|
||||||
glm::max(zw(m_dirty_box[i]), (glm::vec2)(tex_pos + tex_sz)));
|
|
||||||
|
|
||||||
if (P.size() == 4)
|
if (P.size() == 4)
|
||||||
{
|
{
|
||||||
static vertex_t rect[6];
|
static vertex_t rect[6];
|
||||||
@@ -394,13 +392,15 @@ void Canvas::stroke_draw_samples(int i, std::vector<vertex_t>& P)
|
|||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
m_tex[i].unbind();
|
m_tex[i].unbind();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return glm::vec4(tex_pos, tex_pos + tex_sz);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute()
|
std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute(Stroke& stroke) const
|
||||||
{
|
{
|
||||||
std::vector<StrokeFrame> ret;
|
std::vector<StrokeFrame> ret;
|
||||||
const auto& m_brush = m_current_stroke->m_brush;
|
StrokeSample prev = stroke.m_prev_sample;
|
||||||
auto samples = m_current_stroke->compute_samples();
|
auto samples = stroke.compute_samples();
|
||||||
std::array<vertex_t, 4> B = {
|
std::array<vertex_t, 4> B = {
|
||||||
vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} },
|
vertex_t{ {0, 0, 1, 1}, {0, 0}, {0, 0} },
|
||||||
vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} },
|
vertex_t{ {0, 0, 1, 1}, {0, 1}, {0, 1} },
|
||||||
@@ -415,13 +415,7 @@ std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute()
|
|||||||
ret.emplace_back();
|
ret.emplace_back();
|
||||||
auto& f = ret.back();
|
auto& f = ret.back();
|
||||||
|
|
||||||
if (m_mixer_idle)
|
glm::vec2 dx_mix(prev.size * 0.5f, 0), dy_mix(0, prev.size * 0.5f);
|
||||||
{
|
|
||||||
m_mixer_sample = s;
|
|
||||||
m_mixer_idle = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec2 dx_mix(m_mixer_sample.size * 0.5f, 0), dy_mix(0, m_mixer_sample.size * 0.5f);
|
|
||||||
glm::vec2 off_mix[4] = {
|
glm::vec2 off_mix[4] = {
|
||||||
-dx_mix - dy_mix, // A - bottom-left
|
-dx_mix - dy_mix, // A - bottom-left
|
||||||
-dx_mix + dy_mix, // B - top-left
|
-dx_mix + dy_mix, // B - top-left
|
||||||
@@ -442,20 +436,20 @@ std::vector<Canvas::StrokeFrame> Canvas::stroke_draw_compute()
|
|||||||
glm::vec2 mixer_bb_max(0, 0);
|
glm::vec2 mixer_bb_max(0, 0);
|
||||||
for (int j = 0; j < 4; j++)
|
for (int j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
auto p = (xy(m_mixer_sample.pos) + off_mix[j] * glm::orientate2(-s.angle) + glm::vec2(0, 1));
|
auto p = (xy(prev.pos) + s.scale * off_mix[j] * glm::orientate2(-s.angle));
|
||||||
mixer_bb_min = glm::max({ 0, 0 }, glm::min(mixer_bb_min, p));
|
mixer_bb_min = glm::max({ 0, 0 }, glm::min(mixer_bb_min, p));
|
||||||
mixer_bb_max = glm::min(mixer_sz, glm::max(mixer_bb_max, p));
|
mixer_bb_max = glm::min(mixer_sz, glm::max(mixer_bb_max, p));
|
||||||
|
|
||||||
B[j].pos = glm::vec4(xy(s.pos) + off[j] * glm::orientate2(-s.angle), 1, 1);
|
B[j].pos = glm::vec4(xy(s.pos) + s.scale * off[j] * glm::orientate2(-s.angle) - glm::vec2(0, 1), 1, 1);
|
||||||
B[j].uvs2 = p / mixer_sz;
|
B[j].uvs2 = p / mixer_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
f.m_mixer_rect = { mixer_bb_min, mixer_bb_max - mixer_bb_min };
|
f.m_mixer_rect = { mixer_bb_min, mixer_bb_max - mixer_bb_min };
|
||||||
f.col = glm::vec4(s.col, m_brush->m_tip_color.a);
|
f.col = glm::vec4(s.col, 1);
|
||||||
f.pressure = s.flow;
|
f.pressure = s.flow;
|
||||||
f.shapes = stroke_draw_project(B);
|
f.shapes = stroke_draw_project(B);
|
||||||
|
|
||||||
m_mixer_sample = s;
|
prev = s;
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -475,29 +469,18 @@ void Canvas::stroke_draw()
|
|||||||
glGetIntegerv(GL_VIEWPORT, vp);
|
glGetIntegerv(GL_VIEWPORT, vp);
|
||||||
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, cc);
|
||||||
|
|
||||||
const auto& m_brush = m_current_stroke->m_brush;
|
const auto& brush = m_current_stroke->m_brush;
|
||||||
auto& tex = *m_brush->m_tip_texture;
|
const auto& dual_brush = m_dual_stroke->m_brush;
|
||||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||||
|
|
||||||
glViewport(0, 0, m_width, m_height);
|
glViewport(0, 0, m_width, m_height);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
|
||||||
tex.bind();
|
|
||||||
m_sampler_brush.bind(0);
|
m_sampler_brush.bind(0);
|
||||||
m_sampler_bg.bind(1);
|
m_sampler_bg.bind(1);
|
||||||
m_sampler_stencil.bind(2);
|
m_sampler_stencil.bind(2);
|
||||||
m_sampler.bind(3);
|
m_sampler.bind(3);
|
||||||
//m_sampler_linear.bind(5);
|
//m_sampler_linear.bind(5);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
if (m_brush->m_stencil_texture)
|
|
||||||
m_brush->m_stencil_texture->bind();
|
|
||||||
else
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE3);
|
|
||||||
m_mixer.bindTexture();
|
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
ShaderManager::use(kShader::Stroke);
|
ShaderManager::use(kShader::Stroke);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
|
ShaderManager::u_int(kShaderUniform::Tex, 0); // brush
|
||||||
@@ -508,21 +491,32 @@ void Canvas::stroke_draw()
|
|||||||
//ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer
|
//ShaderManager::u_int(kShaderUniform::TexMixA, 4); // mixer
|
||||||
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
ShaderManager::u_vec2(kShaderUniform::Resolution, { m_width, m_height });
|
||||||
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
ShaderManager::u_vec2(kShaderUniform::StencilOffset, stencil_offset);
|
||||||
ShaderManager::u_float(kShaderUniform::StencilAlpha, m_brush->m_tip_stencil);
|
ShaderManager::u_float(kShaderUniform::StencilAlpha, brush->m_tip_stencil);
|
||||||
ShaderManager::u_float(kShaderUniform::MixAlpha, m_brush->m_tip_mix);
|
ShaderManager::u_float(kShaderUniform::MixAlpha, brush->m_tip_mix);
|
||||||
ShaderManager::u_float(kShaderUniform::Wet, m_brush->m_tip_wet);
|
ShaderManager::u_float(kShaderUniform::Wet, brush->m_tip_wet);
|
||||||
ShaderManager::u_float(kShaderUniform::Noise, m_brush->m_tip_noise);
|
ShaderManager::u_float(kShaderUniform::Noise, brush->m_tip_noise);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
ShaderManager::u_mat4(kShaderUniform::MVP, ortho_proj);
|
||||||
|
|
||||||
auto frames = stroke_draw_compute();
|
// DRAW MAIN BRUSH
|
||||||
|
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
brush->m_tip_texture->bind();
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
if (brush->m_stencil_texture)
|
||||||
|
brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
glActiveTexture(GL_TEXTURE3);
|
||||||
|
m_mixer.bindTexture();
|
||||||
|
auto frames = stroke_draw_compute(*m_current_stroke);
|
||||||
for (auto& f : frames)
|
for (auto& f : frames)
|
||||||
{
|
{
|
||||||
if (m_brush->m_tip_mix > 0.f)
|
if (brush->m_tip_mix > 0.f)
|
||||||
{
|
{
|
||||||
stroke_draw_mix(xy(f.m_mixer_rect), zw(f.m_mixer_rect));
|
stroke_draw_mix(xy(f.m_mixer_rect), zw(f.m_mixer_rect));
|
||||||
}
|
}
|
||||||
|
|
||||||
//ShaderManager::use(kShader::Stroke);
|
ShaderManager::use(kShader::Stroke);
|
||||||
ShaderManager::u_vec4(kShaderUniform::Col, f.col);
|
ShaderManager::u_vec4(kShaderUniform::Col, f.col);
|
||||||
ShaderManager::u_float(kShaderUniform::Alpha, f.pressure);
|
ShaderManager::u_float(kShaderUniform::Alpha, f.pressure);
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
@@ -532,22 +526,56 @@ void Canvas::stroke_draw()
|
|||||||
continue;
|
continue;
|
||||||
m_dirty_face[i] = true;
|
m_dirty_face[i] = true;
|
||||||
m_tmp[i].bindFramebuffer();
|
m_tmp[i].bindFramebuffer();
|
||||||
stroke_draw_samples(i, P);
|
auto rect = stroke_draw_samples(i, P);
|
||||||
m_tmp[i].unbindFramebuffer();
|
m_tmp[i].unbindFramebuffer();
|
||||||
|
m_dirty_box[i] = glm::clamp(box_union(m_dirty_box[i], rect), glm::vec4(0), glm::vec4(m_width));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
|
||||||
if (m_brush->m_stencil_texture)
|
|
||||||
m_brush->m_stencil_texture->unbind();
|
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
m_mixer.unbindTexture();
|
m_mixer.unbindTexture();
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
if (brush->m_stencil_texture)
|
||||||
|
brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
brush->m_tip_texture->unbind();
|
||||||
|
|
||||||
|
// DRAW DUAL BRUSH
|
||||||
|
|
||||||
|
if (brush->m_dual_enabled)
|
||||||
|
{
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
dual_brush->m_tip_texture->bind();
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
if (dual_brush->m_stencil_texture)
|
||||||
|
dual_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
auto frames_dual = stroke_draw_compute(*m_dual_stroke);
|
||||||
|
for (auto& f : frames_dual)
|
||||||
|
{
|
||||||
|
ShaderManager::use(kShader::Stroke);
|
||||||
|
ShaderManager::u_vec4(kShaderUniform::Col, f.col);
|
||||||
|
ShaderManager::u_float(kShaderUniform::Alpha, f.pressure);
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
auto& P = f.shapes[i];
|
||||||
|
if (P.size() < 3)
|
||||||
|
continue;
|
||||||
|
m_tmp_dual[i].bindFramebuffer();
|
||||||
|
stroke_draw_samples(i, P);
|
||||||
|
m_tmp_dual[i].unbindFramebuffer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
|
if (dual_brush->m_stencil_texture)
|
||||||
|
dual_brush->m_stencil_texture->unbind();
|
||||||
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
dual_brush->m_tip_texture->unbind();
|
||||||
|
}
|
||||||
|
|
||||||
m_sampler_brush.unbind();
|
m_sampler_brush.unbind();
|
||||||
m_sampler_bg.unbind();
|
m_sampler_bg.unbind();
|
||||||
m_sampler_stencil.unbind();
|
m_sampler_stencil.unbind();
|
||||||
tex.unbind();
|
|
||||||
|
|
||||||
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
glViewport(vp[0], vp[1], vp[2], vp[3]);
|
||||||
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
glClearColor(cc[0], cc[1], cc[2], cc[3]);
|
||||||
@@ -665,7 +693,6 @@ void Canvas::stroke_commit()
|
|||||||
if (!m_dirty || m_layers.empty())
|
if (!m_dirty || m_layers.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_mixer_idle = true;
|
|
||||||
m_dirty = false;
|
m_dirty = false;
|
||||||
m_dirty_stroke = true; // new stroke ready for timelapse capture
|
m_dirty_stroke = true; // new stroke ready for timelapse capture
|
||||||
App::I.redraw = true;
|
App::I.redraw = true;
|
||||||
@@ -763,6 +790,9 @@ void Canvas::stroke_commit()
|
|||||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
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));
|
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||||
|
ShaderManager::u_int(kShaderUniform::TexDual, 3);
|
||||||
|
ShaderManager::u_int(kShaderUniform::UseDual, true);
|
||||||
|
ShaderManager::u_int(kShaderUniform::DualBlendMode, 1);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
m_tex2[i].bind();
|
m_tex2[i].bind();
|
||||||
@@ -771,13 +801,11 @@ void Canvas::stroke_commit()
|
|||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_smask.m_rtt[i].bindTexture();
|
m_smask.m_rtt[i].bindTexture();
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
if (m_current_stroke->m_brush->m_stencil_texture)
|
m_current_stroke->m_brush->m_dual_enabled ?
|
||||||
m_current_stroke->m_brush->m_stencil_texture->bind();
|
m_tmp_dual[i].bindTexture() : glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
else
|
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
if (m_current_stroke->m_brush->m_stencil_texture)
|
if (m_current_stroke->m_brush->m_dual_enabled)
|
||||||
m_current_stroke->m_brush->m_stencil_texture->unbind();
|
m_tmp_dual[i].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_smask.m_rtt[i].unbindTexture();
|
m_smask.m_rtt[i].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
@@ -790,7 +818,7 @@ void Canvas::stroke_commit()
|
|||||||
// ShaderManager::use(kShader::StrokeLayer);
|
// ShaderManager::use(kShader::StrokeLayer);
|
||||||
// ShaderManager::u_int(kShaderUniform::TexBG, 1);
|
// ShaderManager::u_int(kShaderUniform::TexBG, 1);
|
||||||
// ShaderManager::u_int(kShaderUniform::Lock, m_layers[m_current_layer_idx].m_alpha_locked);
|
// 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->brush->m_tip_opacity);
|
||||||
//
|
//
|
||||||
// ShaderManager::u_int(kShaderUniform::Tex, 0);
|
// ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
// ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
// ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||||
@@ -819,14 +847,16 @@ void Canvas::stroke_commit()
|
|||||||
void Canvas::stroke_update(glm::vec3 point, float pressure)
|
void Canvas::stroke_update(glm::vec3 point, float pressure)
|
||||||
{
|
{
|
||||||
m_current_stroke->add_point(point, pressure);
|
m_current_stroke->add_point(point, pressure);
|
||||||
|
m_dual_stroke->add_point(point, pressure);
|
||||||
}
|
}
|
||||||
void Canvas::stroke_start(glm::vec3 point, float pressure, const std::shared_ptr<Brush>& brush)
|
void Canvas::stroke_start(glm::vec3 point, float pressure)
|
||||||
{
|
{
|
||||||
// need to commit this now before starting a new stroke
|
// need to commit this now before starting a new stroke
|
||||||
if (m_current_stroke && m_commit_delayed)
|
if (m_current_stroke && m_commit_delayed)
|
||||||
{
|
{
|
||||||
stroke_commit();
|
stroke_commit();
|
||||||
m_current_stroke = nullptr;
|
m_current_stroke = nullptr;
|
||||||
|
m_dual_stroke = nullptr;
|
||||||
m_show_tmp = false;
|
m_show_tmp = false;
|
||||||
m_commit_delayed = false;
|
m_commit_delayed = false;
|
||||||
}
|
}
|
||||||
@@ -836,9 +866,15 @@ void Canvas::stroke_start(glm::vec3 point, float pressure, const std::shared_ptr
|
|||||||
m_current_stroke = std::make_unique<Stroke>();
|
m_current_stroke = std::make_unique<Stroke>();
|
||||||
m_current_stroke->m_camera.rot = m_cam_rot;
|
m_current_stroke->m_camera.rot = m_cam_rot;
|
||||||
m_current_stroke->m_camera.fov = m_cam_fov;
|
m_current_stroke->m_camera.fov = m_cam_fov;
|
||||||
m_current_stroke->start(brush);
|
m_current_stroke->start(m_current_brush);
|
||||||
m_current_stroke->add_point(point, pressure);
|
m_current_stroke->add_point(point, pressure);
|
||||||
|
|
||||||
|
m_dual_stroke = std::make_unique<Stroke>();
|
||||||
|
m_dual_stroke->m_camera.rot = m_cam_rot;
|
||||||
|
m_dual_stroke->m_camera.fov = m_cam_fov;
|
||||||
|
m_dual_stroke->start(m_dual_brush);
|
||||||
|
m_dual_stroke->add_point(point, pressure);
|
||||||
|
|
||||||
for (int i = 0; i < 6; i++)
|
for (int i = 0; i < 6; i++)
|
||||||
{
|
{
|
||||||
m_dirty_box[i] = glm::vec4(m_width, m_height, 0, 0); // reset bounding box
|
m_dirty_box[i] = glm::vec4(m_width, m_height, 0, 0); // reset bounding box
|
||||||
@@ -847,6 +883,13 @@ void Canvas::stroke_start(glm::vec3 point, float pressure, const std::shared_ptr
|
|||||||
m_tmp[i].bindFramebuffer();
|
m_tmp[i].bindFramebuffer();
|
||||||
m_tmp[i].clear({ 0, 0, 0, 0 });
|
m_tmp[i].clear({ 0, 0, 0, 0 });
|
||||||
m_tmp[i].unbindFramebuffer();
|
m_tmp[i].unbindFramebuffer();
|
||||||
|
|
||||||
|
if (m_current_stroke->m_brush->m_dual_enabled)
|
||||||
|
{
|
||||||
|
m_tmp_dual[i].bindFramebuffer();
|
||||||
|
m_tmp_dual[i].clear({ 0, 0, 0, 0 });
|
||||||
|
m_tmp_dual[i].unbindFramebuffer();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_show_tmp = true;
|
m_show_tmp = true;
|
||||||
}
|
}
|
||||||
@@ -934,6 +977,7 @@ void Canvas::layer_merge(int source_idx, int dest_idx) // m_layer index
|
|||||||
ShaderManager::u_int(kShaderUniform::Lock, false);
|
ShaderManager::u_int(kShaderUniform::Lock, false);
|
||||||
ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[source_idx].m_blend_mode);
|
ShaderManager::u_int(kShaderUniform::BlendMode, m_layers[source_idx].m_blend_mode);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-.5f, .5f, -.5f, .5f, -1.f, 1.f));
|
||||||
|
ShaderManager::u_int(kShaderUniform::UseDual, false);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
m_tex2[i].bind();
|
m_tex2[i].bind();
|
||||||
@@ -971,9 +1015,11 @@ void Canvas::resize(int width, int height)
|
|||||||
{
|
{
|
||||||
#if defined(__IOS__) || defined(__ANDROID__)
|
#if defined(__IOS__) || defined(__ANDROID__)
|
||||||
m_tmp[i].create(width, height, -1, GL_RGBA8);
|
m_tmp[i].create(width, height, -1, GL_RGBA8);
|
||||||
|
m_tmp_dual[i].create(width, height, -1, GL_RGBA8);
|
||||||
m_tex[i].create(width, height, GL_RGBA8);
|
m_tex[i].create(width, height, GL_RGBA8);
|
||||||
#else
|
#else
|
||||||
m_tmp[i].create(width, height, -1, GL_RGBA32F);
|
m_tmp[i].create(width, height, -1, GL_RGBA32F);
|
||||||
|
m_tmp_dual[i].create(width, height, -1, GL_RGBA32F);
|
||||||
m_tex[i].create(width, height, GL_RGBA32F);
|
m_tex[i].create(width, height, GL_RGBA32F);
|
||||||
#endif
|
#endif
|
||||||
m_tex2[i].create(width, height, GL_RGBA8);
|
m_tex2[i].create(width, height, GL_RGBA8);
|
||||||
@@ -992,10 +1038,12 @@ bool Canvas::create(int width, int height)
|
|||||||
{
|
{
|
||||||
#if defined(__IOS__) || defined(__ANDROID__)
|
#if defined(__IOS__) || defined(__ANDROID__)
|
||||||
m_tmp[i].create(width, height, -1, GL_RGBA8);
|
m_tmp[i].create(width, height, -1, GL_RGBA8);
|
||||||
|
m_tmp_dual[i].create(width, height, -1, GL_RGBA8);
|
||||||
m_tex[i].create(width, height, GL_RGBA8);
|
m_tex[i].create(width, height, GL_RGBA8);
|
||||||
m_sampler_brush.create();
|
m_sampler_brush.create();
|
||||||
#else
|
#else
|
||||||
m_tmp[i].create(width, height, -1, GL_RGBA32F);
|
m_tmp[i].create(width, height, -1, GL_RGBA32F);
|
||||||
|
m_tmp_dual[i].create(width, height, -1, GL_RGBA32F);
|
||||||
m_tex[i].create(width, height, GL_RGBA32F);
|
m_tex[i].create(width, height, GL_RGBA32F);
|
||||||
m_sampler_brush.create(GL_LINEAR, GL_CLAMP_TO_BORDER);
|
m_sampler_brush.create(GL_LINEAR, GL_CLAMP_TO_BORDER);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
14
src/canvas.h
14
src/canvas.h
@@ -161,6 +161,7 @@ public:
|
|||||||
bool m_use_instanced = false;
|
bool m_use_instanced = false;
|
||||||
int m_current_layer_idx = 0;
|
int m_current_layer_idx = 0;
|
||||||
std::unique_ptr<Stroke> m_current_stroke;
|
std::unique_ptr<Stroke> m_current_stroke;
|
||||||
|
std::unique_ptr<Stroke> m_dual_stroke;
|
||||||
bool m_show_tmp = false;
|
bool m_show_tmp = false;
|
||||||
std::vector<Layer> m_layers;
|
std::vector<Layer> m_layers;
|
||||||
std::vector<int> m_order;
|
std::vector<int> m_order;
|
||||||
@@ -172,10 +173,9 @@ public:
|
|||||||
Layer m_smask; // selection mask
|
Layer m_smask; // selection mask
|
||||||
bool m_smask_active = false;
|
bool m_smask_active = false;
|
||||||
RTT m_tmp[6];
|
RTT m_tmp[6];
|
||||||
|
RTT m_tmp_dual[6];
|
||||||
RTT m_mixer;
|
RTT m_mixer;
|
||||||
float m_mixer_scale = 1;
|
float m_mixer_scale = 1;
|
||||||
StrokeSample m_mixer_sample;
|
|
||||||
bool m_mixer_idle = true;
|
|
||||||
Texture2D m_brush_mix;
|
Texture2D m_brush_mix;
|
||||||
Texture2D m_tex[6];
|
Texture2D m_tex[6];
|
||||||
Texture2D m_tex2[6];
|
Texture2D m_tex2[6];
|
||||||
@@ -200,6 +200,7 @@ public:
|
|||||||
glm::vec2 m_cur_pos;
|
glm::vec2 m_cur_pos;
|
||||||
|
|
||||||
std::shared_ptr<Brush> m_current_brush;
|
std::shared_ptr<Brush> m_current_brush;
|
||||||
|
std::shared_ptr<Brush> m_dual_brush;
|
||||||
|
|
||||||
static std::vector<CanvasMode*> modes[];
|
static std::vector<CanvasMode*> modes[];
|
||||||
std::vector<CanvasMode*>* m_mode = nullptr;
|
std::vector<CanvasMode*>* m_mode = nullptr;
|
||||||
@@ -229,12 +230,13 @@ public:
|
|||||||
void layer_add(std::string name);
|
void layer_add(std::string name);
|
||||||
void layer_order(int idx, int pos);
|
void layer_order(int idx, int pos);
|
||||||
void layer_merge(int source_idx, int dest_idx);
|
void layer_merge(int source_idx, int dest_idx);
|
||||||
void stroke_start(glm::vec3 point, float pressure, const std::shared_ptr<Brush>& brush);
|
void stroke_start(glm::vec3 point, float pressure);
|
||||||
void stroke_update(glm::vec3 point, float pressure);
|
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_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz);
|
||||||
std::array<std::vector<vertex_t>, 6> stroke_draw_project(std::array<vertex_t, 4>& B);
|
std::array<std::vector<vertex_t>, 6> stroke_draw_project(std::array<vertex_t, 4>& B) const;
|
||||||
void stroke_draw_samples(int i, std::vector<vertex_t>& P);
|
// return rect {origin, size}
|
||||||
std::vector<StrokeFrame> stroke_draw_compute();
|
glm::vec4 stroke_draw_samples(int i, std::vector<vertex_t>& P);
|
||||||
|
std::vector<StrokeFrame> stroke_draw_compute(Stroke& stroke) const;
|
||||||
void stroke_draw();
|
void stroke_draw();
|
||||||
void stroke_end();
|
void stroke_end();
|
||||||
void stroke_cancel();
|
void stroke_cancel();
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Canvas::I->stroke_start({ loc, 0 }, me->m_pressure, Canvas::I->m_current_brush);
|
Canvas::I->stroke_start({ loc, 0 }, me->m_pressure);
|
||||||
}
|
}
|
||||||
m_dragging = true;
|
m_dragging = true;
|
||||||
node->mouse_capture();
|
node->mouse_capture();
|
||||||
@@ -203,22 +203,26 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const
|
|||||||
{
|
{
|
||||||
if (m_draw_tip)
|
if (m_draw_tip)
|
||||||
{
|
{
|
||||||
|
const auto& brush = Canvas::I->m_current_brush;
|
||||||
auto pos = m_resizing ? m_size_pos_start : m_cur_pos;
|
auto pos = m_resizing ? m_size_pos_start : m_cur_pos;
|
||||||
if (App::I.keys[(int)kKey::KeyAlt] && !m_resizing)
|
if (App::I.keys[(int)kKey::KeyAlt] && !m_resizing)
|
||||||
pos.x = pos.x - Canvas::I->m_current_brush->m_tip_size * 500.f;
|
pos.x = pos.x - brush->m_tip_size * 500.f;
|
||||||
ShaderManager::use(kShader::StrokePreview);
|
ShaderManager::use(kShader::StrokePreview);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
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_fix = 1.f / glm::tan(glm::radians(Canvas::I->m_cam_fov * 0.5f));
|
||||||
float tip_scale = Canvas::I->m_current_brush->m_tip_size * 800.f * tip_scale_fix;
|
float tip_angle = brush->m_tip_angle * (float)(M_PI * 2.0);
|
||||||
float tip_angle = Canvas::I->m_current_brush->m_tip_angle * (float)(M_PI * 2.0);
|
glm::vec2 tip_scale = glm::vec2(brush->m_tip_size * 800.f * tip_scale_fix) *
|
||||||
|
glm::vec2(brush->m_tip_flipx ? -1 : 1, brush->m_tip_flipy ? -1.f : 1.f) *
|
||||||
|
glm::vec2((brush->m_tip_aspect <= 0.5 ? brush->m_tip_aspect * 2.f : 1.f),
|
||||||
|
(brush->m_tip_aspect > 0.5 ? 1.f - (brush->m_tip_aspect - .5f) * 2.f : 1.f));
|
||||||
glm::vec2 tip_offset = glm::vec2(0);
|
glm::vec2 tip_offset = glm::vec2(0);
|
||||||
auto tip_color = glm::vec4(glm::vec3(Canvas::I->m_current_brush->m_tip_color), 1);
|
auto tip_color = glm::vec4(glm::vec3(brush->m_tip_color), 1.f);
|
||||||
if (Canvas::I->m_current_stroke)
|
if (Canvas::I->m_current_stroke)
|
||||||
{
|
{
|
||||||
const auto& s = Canvas::I->m_current_stroke->m_prev_sample;
|
const auto& s = Canvas::I->m_current_stroke->m_prev_sample;
|
||||||
if (s.size > 0.f)
|
if (s.size > 0.f)
|
||||||
{
|
{
|
||||||
tip_scale = s.size;
|
tip_scale = (brush->m_tip_size * 800.f * tip_scale_fix) * s.scale;
|
||||||
tip_angle = s.angle;
|
tip_angle = s.angle;
|
||||||
tip_offset = s.pos - s.origin;
|
tip_offset = s.pos - s.origin;
|
||||||
tip_color = glm::vec4(s.col, s.flow);
|
tip_color = glm::vec4(s.col, s.flow);
|
||||||
@@ -229,13 +233,13 @@ void CanvasModePen::on_Draw(const glm::mat4& ortho, const glm::mat4& proj, const
|
|||||||
glm::scale(glm::vec3(1, -1, 1)) *
|
glm::scale(glm::vec3(1, -1, 1)) *
|
||||||
ortho *
|
ortho *
|
||||||
glm::translate(glm::vec3(pos + tip_offset, 0)) *
|
glm::translate(glm::vec3(pos + tip_offset, 0)) *
|
||||||
glm::scale(glm::vec3(tip_scale)) *
|
glm::eulerAngleZ(tip_angle) *
|
||||||
glm::eulerAngleZ(tip_angle)
|
glm::scale(glm::vec3(tip_scale, 1))
|
||||||
);
|
);
|
||||||
bool blend = glIsEnabled(GL_BLEND);
|
bool blend = glIsEnabled(GL_BLEND);
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
auto& tex = *Canvas::I->m_current_brush->m_tip_texture;
|
auto& tex = *brush->m_tip_texture;
|
||||||
tex.bind();
|
tex.bind();
|
||||||
Canvas::I->m_sampler_brush.bind(0);
|
Canvas::I->m_sampler_brush.bind(0);
|
||||||
Canvas::I->m_plane.draw_fill();
|
Canvas::I->m_plane.draw_fill();
|
||||||
@@ -281,7 +285,7 @@ void CanvasModeLine::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
|||||||
node->mouse_release();
|
node->mouse_release();
|
||||||
if (m_dragging)
|
if (m_dragging)
|
||||||
{
|
{
|
||||||
Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f, Canvas::I->m_current_brush);
|
Canvas::I->stroke_start({ m_drag_start, 0 }, 1.f);
|
||||||
Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f);
|
Canvas::I->stroke_update({ m_drag_pos, 0 }, 1.f);
|
||||||
Canvas::I->stroke_end();
|
Canvas::I->stroke_end();
|
||||||
}
|
}
|
||||||
@@ -1156,6 +1160,7 @@ void CanvasModeTransform::leave()
|
|||||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, true);
|
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, true);
|
||||||
ShaderManager::u_vec2(kShaderUniform::Resolution, Canvas::I->m_size);
|
ShaderManager::u_vec2(kShaderUniform::Resolution, Canvas::I->m_size);
|
||||||
ShaderManager::u_int(kShaderUniform::BlendMode, 0);
|
ShaderManager::u_int(kShaderUniform::BlendMode, 0);
|
||||||
|
ShaderManager::u_int(kShaderUniform::UseDual, false);
|
||||||
|
|
||||||
Canvas::I->m_sampler_bg.bind(1);
|
Canvas::I->m_sampler_bg.bind(1);
|
||||||
Canvas::I->m_sampler_bg.bind(0);
|
Canvas::I->m_sampler_bg.bind(0);
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ bool LayoutManager::load(const char* path)
|
|||||||
}
|
}
|
||||||
current = current->NextSiblingElement("layout");
|
current = current->NextSiblingElement("layout");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (on_loaded)
|
if (on_loaded)
|
||||||
on_loaded();
|
on_loaded();
|
||||||
m_loaded = true;
|
m_loaded = true;
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ void NodeButton::clone_copy(Node* dest) const
|
|||||||
|
|
||||||
void NodeButton::init()
|
void NodeButton::init()
|
||||||
{
|
{
|
||||||
|
Node::init();
|
||||||
m_border = new NodeBorder();
|
m_border = new NodeBorder();
|
||||||
m_text = new NodeText();
|
m_text = new NodeText();
|
||||||
add_child(m_border);
|
add_child(m_border);
|
||||||
@@ -48,6 +49,7 @@ void NodeButton::init()
|
|||||||
|
|
||||||
void NodeButton::create()
|
void NodeButton::create()
|
||||||
{
|
{
|
||||||
|
Node::create();
|
||||||
m_border->create();
|
m_border->create();
|
||||||
m_text->create();
|
m_text->create();
|
||||||
m_border->m_mouse_ignore = false;
|
m_border->m_mouse_ignore = false;
|
||||||
@@ -56,6 +58,7 @@ void NodeButton::create()
|
|||||||
|
|
||||||
void NodeButton::loaded()
|
void NodeButton::loaded()
|
||||||
{
|
{
|
||||||
|
Node::loaded();
|
||||||
m_border->m_thinkness = 1;
|
m_border->m_thinkness = 1;
|
||||||
m_border->m_border_color = glm::vec4(0, 0, 0, 1);
|
m_border->m_border_color = glm::vec4(0, 0, 0, 1);
|
||||||
m_border->m_color = color_normal;
|
m_border->m_color = color_normal;
|
||||||
|
|||||||
@@ -213,13 +213,24 @@ void NodeCanvas::draw()
|
|||||||
ShaderManager::u_int(kShaderUniform::UseFragCoordUV2, false);
|
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);
|
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp_z);
|
||||||
|
ShaderManager::u_int(kShaderUniform::TexDual, 3);
|
||||||
|
ShaderManager::u_int(kShaderUniform::UseDual, true);
|
||||||
|
ShaderManager::u_int(kShaderUniform::DualBlendMode, 1);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
m_canvas->m_layers[layer_index].m_rtt[plane_index].bindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
m_canvas->m_tmp[plane_index].bindTexture();
|
m_canvas->m_tmp[plane_index].bindTexture();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_canvas->m_smask.m_rtt[plane_index].bindTexture();
|
m_canvas->m_smask.m_rtt[plane_index].bindTexture();
|
||||||
|
glActiveTexture(GL_TEXTURE3);
|
||||||
|
m_canvas->m_current_stroke->m_brush->m_dual_enabled ?
|
||||||
|
m_canvas->m_tmp_dual[plane_index].bindTexture() :
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_face_plane.draw_fill();
|
m_face_plane.draw_fill();
|
||||||
|
if (m_canvas->m_current_stroke->m_brush->m_dual_enabled)
|
||||||
|
m_canvas->m_tmp_dual[plane_index].unbindTexture();
|
||||||
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_canvas->m_smask.m_rtt[plane_index].unbindTexture();
|
m_canvas->m_smask.m_rtt[plane_index].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
m_canvas->m_tmp[plane_index].unbindTexture();
|
m_canvas->m_tmp[plane_index].unbindTexture();
|
||||||
@@ -329,9 +340,9 @@ void NodeCanvas::draw()
|
|||||||
for (int plane_index = 0; plane_index < 6; plane_index++)
|
for (int plane_index = 0; plane_index < 6; plane_index++)
|
||||||
{
|
{
|
||||||
auto plane_mvp = proj * camera *
|
auto plane_mvp = proj * camera *
|
||||||
glm::scale(glm::vec3(m_canvas->m_order.size() + 500)) *
|
glm::scale(glm::vec3(m_canvas->m_order.size() + 500.f)) *
|
||||||
m_canvas->m_plane_transform[plane_index] *
|
m_canvas->m_plane_transform[plane_index] *
|
||||||
glm::translate(glm::vec3(0, 0, -1));
|
glm::translate(glm::vec3(0, 0, -1.f));
|
||||||
|
|
||||||
ShaderManager::use(kShader::Checkerboard);
|
ShaderManager::use(kShader::Checkerboard);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp);
|
ShaderManager::u_mat4(kShaderUniform::MVP, plane_mvp);
|
||||||
@@ -344,7 +355,7 @@ void NodeCanvas::draw()
|
|||||||
m_cache_rtt.bindTexture();
|
m_cache_rtt.bindTexture();
|
||||||
ShaderManager::use(kShader::Texture);
|
ShaderManager::use(kShader::Texture);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho(-1, 1, -1, 1));
|
ShaderManager::u_mat4(kShaderUniform::MVP, glm::ortho<float>(-1, 1, -1, 1));
|
||||||
m_face_plane.draw_fill();
|
m_face_plane.draw_fill();
|
||||||
m_cache_rtt.unbindTexture();
|
m_cache_rtt.unbindTexture();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ void NodeCheckBox::clone_children(Node* dest) const
|
|||||||
|
|
||||||
void NodeCheckBox::init()
|
void NodeCheckBox::init()
|
||||||
{
|
{
|
||||||
|
Node::init();
|
||||||
m_outer = new NodeBorder();
|
m_outer = new NodeBorder();
|
||||||
m_inner = new NodeBorder();
|
m_inner = new NodeBorder();
|
||||||
add_child(m_outer);
|
add_child(m_outer);
|
||||||
@@ -44,6 +45,7 @@ void NodeCheckBox::init()
|
|||||||
|
|
||||||
void NodeCheckBox::create()
|
void NodeCheckBox::create()
|
||||||
{
|
{
|
||||||
|
Node::create();
|
||||||
m_outer->create();
|
m_outer->create();
|
||||||
m_inner->create();
|
m_inner->create();
|
||||||
if (!m_icon_path.empty())
|
if (!m_icon_path.empty())
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ void NodeImage::clone_copy(Node* dest) const
|
|||||||
|
|
||||||
void NodeImage::create()
|
void NodeImage::create()
|
||||||
{
|
{
|
||||||
|
Node::create();
|
||||||
if (!m_path.empty() && TextureManager::load(m_path.c_str(), m_use_mipmaps))
|
if (!m_path.empty() && TextureManager::load(m_path.c_str(), m_use_mipmaps))
|
||||||
{
|
{
|
||||||
//LOG("load image node %s", m_path.c_str());
|
//LOG("load image node %s", m_path.c_str());
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ void NodePanelBrush::init()
|
|||||||
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
|
std::string path_thumb = App::I.data_path + "/brushes/thumbs/" + name + ".png";
|
||||||
|
|
||||||
img = img.resize_squared(glm::u8vec4(255));
|
img = img.resize_squared(glm::u8vec4(255));
|
||||||
img.gayscale_alpha();
|
//img.gayscale_alpha();
|
||||||
|
|
||||||
auto thumb = img.resize(64, 64);
|
auto thumb = img.resize(64, 64);
|
||||||
thumb.save(path_thumb);
|
thumb.save(path_thumb);
|
||||||
@@ -533,13 +533,17 @@ bool NodePanelBrushPreset::save()
|
|||||||
i.m_name_len = b->m_brush->m_name.size();
|
i.m_name_len = b->m_brush->m_name.size();
|
||||||
i.m_brush_path_len = b->m_brush->m_brush_path.size();
|
i.m_brush_path_len = b->m_brush->m_brush_path.size();
|
||||||
i.m_brush_thumb_path_len = b->m_brush->m_brush_thumb_path.size();
|
i.m_brush_thumb_path_len = b->m_brush->m_brush_thumb_path.size();
|
||||||
|
i.m_dual_path_len = b->m_brush->m_brush_path.size();
|
||||||
|
i.m_dual_thumb_path_len = b->m_brush->m_brush_thumb_path.size();
|
||||||
i.m_stencil_path_len = b->m_brush->m_stencil_path.size();
|
i.m_stencil_path_len = b->m_brush->m_stencil_path.size();
|
||||||
|
i.m_stencil_thumb_path_len = b->m_brush->m_stencil_thumb_path.size();
|
||||||
i.m_tip_color = b->m_brush->m_tip_color;
|
i.m_tip_color = b->m_brush->m_tip_color;
|
||||||
i.m_tip_size = b->m_brush->m_tip_size;
|
i.m_tip_size = b->m_brush->m_tip_size;
|
||||||
i.m_tip_spacing = b->m_brush->m_tip_spacing;
|
i.m_tip_spacing = b->m_brush->m_tip_spacing;
|
||||||
i.m_tip_flow = b->m_brush->m_tip_flow;
|
i.m_tip_flow = b->m_brush->m_tip_flow;
|
||||||
i.m_tip_opacity = b->m_brush->m_tip_opacity;
|
i.m_tip_opacity = b->m_brush->m_tip_opacity;
|
||||||
i.m_tip_angle = b->m_brush->m_tip_angle;
|
i.m_tip_angle = b->m_brush->m_tip_angle;
|
||||||
|
i.m_tip_angle_delay = b->m_brush->m_tip_angle_delay;
|
||||||
i.m_tip_mix = b->m_brush->m_tip_mix;
|
i.m_tip_mix = b->m_brush->m_tip_mix;
|
||||||
i.m_tip_stencil = b->m_brush->m_tip_stencil;
|
i.m_tip_stencil = b->m_brush->m_tip_stencil;
|
||||||
i.m_tip_wet = b->m_brush->m_tip_wet;
|
i.m_tip_wet = b->m_brush->m_tip_wet;
|
||||||
@@ -550,9 +554,6 @@ bool NodePanelBrushPreset::save()
|
|||||||
i.m_tip_angle_follow = b->m_brush->m_tip_angle_follow;
|
i.m_tip_angle_follow = b->m_brush->m_tip_angle_follow;
|
||||||
i.m_tip_flow_pressure = b->m_brush->m_tip_flow_pressure;
|
i.m_tip_flow_pressure = b->m_brush->m_tip_flow_pressure;
|
||||||
i.m_tip_size_pressure = b->m_brush->m_tip_size_pressure;
|
i.m_tip_size_pressure = b->m_brush->m_tip_size_pressure;
|
||||||
i.m_tip_hue_pressure = b->m_brush->m_tip_hue_pressure;
|
|
||||||
i.m_tip_sat_pressure = b->m_brush->m_tip_sat_pressure;
|
|
||||||
i.m_tip_val_pressure = b->m_brush->m_tip_val_pressure;
|
|
||||||
i.m_jitter_scale = b->m_brush->m_jitter_scale;
|
i.m_jitter_scale = b->m_brush->m_jitter_scale;
|
||||||
i.m_jitter_angle = b->m_brush->m_jitter_angle;
|
i.m_jitter_angle = b->m_brush->m_jitter_angle;
|
||||||
i.m_jitter_spread = b->m_brush->m_jitter_spread;
|
i.m_jitter_spread = b->m_brush->m_jitter_spread;
|
||||||
@@ -561,11 +562,33 @@ bool NodePanelBrushPreset::save()
|
|||||||
i.m_jitter_sat = b->m_brush->m_jitter_sat;
|
i.m_jitter_sat = b->m_brush->m_jitter_sat;
|
||||||
i.m_jitter_val = b->m_brush->m_jitter_val;
|
i.m_jitter_val = b->m_brush->m_jitter_val;
|
||||||
i.m_blend_mode = b->m_brush->m_blend_mode;
|
i.m_blend_mode = b->m_brush->m_blend_mode;
|
||||||
|
|
||||||
|
i.m_tip_invert = b->m_brush->m_tip_invert;
|
||||||
|
i.m_tip_flipx = b->m_brush->m_tip_flipx;
|
||||||
|
i.m_tip_flipy = b->m_brush->m_tip_flipy;
|
||||||
|
i.m_tex_enabled = b->m_brush->m_tex_enabled;
|
||||||
|
i.m_dual_enabled = b->m_brush->m_dual_enabled;
|
||||||
|
i.m_dual_blend_mode = b->m_brush->m_dual_blend_mode;
|
||||||
|
i.m_dual_randflip = b->m_brush->m_dual_randflip;
|
||||||
|
i.m_dual_size = b->m_brush->m_dual_size;
|
||||||
|
i.m_dual_spacing = b->m_brush->m_dual_spacing;
|
||||||
|
i.m_dual_scatter = b->m_brush->m_dual_scatter;
|
||||||
|
i.m_dual_scatter_axis = b->m_brush->m_dual_scatter_axis;
|
||||||
|
i.m_dual_invert = b->m_brush->m_dual_invert;
|
||||||
|
i.m_dual_flipx = b->m_brush->m_dual_flipx;
|
||||||
|
i.m_dual_flipy = b->m_brush->m_dual_flipy;
|
||||||
|
i.m_tip_randflipx = b->m_brush->m_tip_randflipx;
|
||||||
|
i.m_tip_randflipy = b->m_brush->m_tip_randflipy;
|
||||||
|
i.m_tip_aspect = b->m_brush->m_tip_aspect;
|
||||||
|
|
||||||
fwrite(&i, sizeof(i), 1, fp);
|
fwrite(&i, sizeof(i), 1, fp);
|
||||||
fwrite(b->m_brush->m_name.c_str(), 1, b->m_brush->m_name.size(), fp);
|
fwrite(b->m_brush->m_name.c_str(), 1, b->m_brush->m_name.size(), fp);
|
||||||
fwrite(b->m_brush->m_brush_path.c_str(), 1, b->m_brush->m_brush_path.size(), fp);
|
fwrite(b->m_brush->m_brush_path.c_str(), 1, b->m_brush->m_brush_path.size(), fp);
|
||||||
fwrite(b->m_brush->m_brush_thumb_path.c_str(), 1, b->m_brush->m_brush_thumb_path.size(), fp);
|
fwrite(b->m_brush->m_brush_thumb_path.c_str(), 1, b->m_brush->m_brush_thumb_path.size(), fp);
|
||||||
|
fwrite(b->m_brush->m_dual_path.c_str(), 1, b->m_brush->m_brush_path.size(), fp);
|
||||||
|
fwrite(b->m_brush->m_dual_thumb_path.c_str(), 1, b->m_brush->m_brush_thumb_path.size(), fp);
|
||||||
fwrite(b->m_brush->m_stencil_path.c_str(), 1, b->m_brush->m_stencil_path.size(), fp);
|
fwrite(b->m_brush->m_stencil_path.c_str(), 1, b->m_brush->m_stencil_path.size(), fp);
|
||||||
|
fwrite(b->m_brush->m_stencil_thumb_path.c_str(), 1, b->m_brush->m_stencil_thumb_path.size(), fp);
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
return true;
|
return true;
|
||||||
@@ -604,6 +627,7 @@ bool NodePanelBrushPreset::restore()
|
|||||||
b->m_tip_flow = i.m_tip_flow;
|
b->m_tip_flow = i.m_tip_flow;
|
||||||
b->m_tip_opacity = i.m_tip_opacity;
|
b->m_tip_opacity = i.m_tip_opacity;
|
||||||
b->m_tip_angle = i.m_tip_angle;
|
b->m_tip_angle = i.m_tip_angle;
|
||||||
|
b->m_tip_angle_delay = i.m_tip_angle_delay;
|
||||||
b->m_tip_mix = i.m_tip_mix;
|
b->m_tip_mix = i.m_tip_mix;
|
||||||
b->m_tip_stencil = i.m_tip_stencil;
|
b->m_tip_stencil = i.m_tip_stencil;
|
||||||
b->m_tip_wet = i.m_tip_wet;
|
b->m_tip_wet = i.m_tip_wet;
|
||||||
@@ -614,9 +638,6 @@ bool NodePanelBrushPreset::restore()
|
|||||||
b->m_tip_angle_follow = i.m_tip_angle_follow;
|
b->m_tip_angle_follow = i.m_tip_angle_follow;
|
||||||
b->m_tip_flow_pressure = i.m_tip_flow_pressure;
|
b->m_tip_flow_pressure = i.m_tip_flow_pressure;
|
||||||
b->m_tip_size_pressure = i.m_tip_size_pressure;
|
b->m_tip_size_pressure = i.m_tip_size_pressure;
|
||||||
b->m_tip_hue_pressure = i.m_tip_hue_pressure;
|
|
||||||
b->m_tip_sat_pressure = i.m_tip_sat_pressure;
|
|
||||||
b->m_tip_val_pressure = i.m_tip_val_pressure;
|
|
||||||
b->m_jitter_scale = i.m_jitter_scale;
|
b->m_jitter_scale = i.m_jitter_scale;
|
||||||
b->m_jitter_angle = i.m_jitter_angle;
|
b->m_jitter_angle = i.m_jitter_angle;
|
||||||
b->m_jitter_spread = i.m_jitter_spread;
|
b->m_jitter_spread = i.m_jitter_spread;
|
||||||
@@ -625,14 +646,37 @@ bool NodePanelBrushPreset::restore()
|
|||||||
b->m_jitter_sat = i.m_jitter_sat;
|
b->m_jitter_sat = i.m_jitter_sat;
|
||||||
b->m_jitter_val = i.m_jitter_val;
|
b->m_jitter_val = i.m_jitter_val;
|
||||||
b->m_blend_mode = i.m_blend_mode;
|
b->m_blend_mode = i.m_blend_mode;
|
||||||
|
|
||||||
|
b->m_tip_invert = i.m_tip_invert;
|
||||||
|
b->m_tip_flipx = i.m_tip_flipx;
|
||||||
|
b->m_tip_flipy = i.m_tip_flipy;
|
||||||
|
b->m_tex_enabled = i.m_tex_enabled;
|
||||||
|
b->m_dual_enabled = i.m_dual_enabled;
|
||||||
|
b->m_dual_blend_mode = i.m_dual_blend_mode;
|
||||||
|
b->m_dual_randflip = i.m_dual_randflip;
|
||||||
|
b->m_dual_size = i.m_dual_size;
|
||||||
|
b->m_dual_spacing = i.m_dual_spacing;
|
||||||
|
b->m_dual_scatter = i.m_dual_scatter;
|
||||||
|
b->m_dual_scatter_axis = i.m_dual_scatter_axis;
|
||||||
|
b->m_dual_invert = i.m_dual_invert;
|
||||||
|
b->m_dual_flipx = i.m_dual_flipx;
|
||||||
|
b->m_dual_flipy = i.m_dual_flipy;
|
||||||
|
b->m_tip_aspect = i.m_tip_aspect;
|
||||||
|
|
||||||
b->m_name.resize(i.m_name_len);
|
b->m_name.resize(i.m_name_len);
|
||||||
b->m_brush_path.resize(i.m_brush_path_len);
|
b->m_brush_path.resize(i.m_brush_path_len);
|
||||||
b->m_brush_thumb_path.resize(i.m_brush_thumb_path_len);
|
b->m_brush_thumb_path.resize(i.m_brush_thumb_path_len);
|
||||||
|
b->m_dual_path.resize(i.m_brush_path_len);
|
||||||
|
b->m_dual_thumb_path.resize(i.m_brush_thumb_path_len);
|
||||||
b->m_stencil_path.resize(i.m_stencil_path_len);
|
b->m_stencil_path.resize(i.m_stencil_path_len);
|
||||||
|
b->m_stencil_thumb_path.resize(i.m_stencil_thumb_path_len);
|
||||||
fread((char*)b->m_name.c_str(), 1, b->m_name.size(), fp);
|
fread((char*)b->m_name.c_str(), 1, b->m_name.size(), fp);
|
||||||
fread((char*)b->m_brush_path.c_str(), 1, b->m_brush_path.size(), fp);
|
fread((char*)b->m_brush_path.c_str(), 1, b->m_brush_path.size(), fp);
|
||||||
fread((char*)b->m_brush_thumb_path.c_str(), 1, b->m_brush_thumb_path.size(), fp);
|
fread((char*)b->m_brush_thumb_path.c_str(), 1, b->m_brush_thumb_path.size(), fp);
|
||||||
|
fread((char*)b->m_dual_path.c_str(), 1, b->m_brush_path.size(), fp);
|
||||||
|
fread((char*)b->m_dual_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);
|
fread((char*)b->m_stencil_path.c_str(), 1, b->m_stencil_path.size(), fp);
|
||||||
|
fread((char*)b->m_stencil_thumb_path.c_str(), 1, b->m_stencil_thumb_path.size(), fp);
|
||||||
|
|
||||||
if (b->load_texture(b->m_brush_path, b->m_brush_thumb_path))
|
if (b->load_texture(b->m_brush_path, b->m_brush_thumb_path))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -92,15 +92,23 @@ class NodePanelBrushPreset : public Node
|
|||||||
};
|
};
|
||||||
struct item_t {
|
struct item_t {
|
||||||
int m_name_len = 0;
|
int m_name_len = 0;
|
||||||
|
|
||||||
int m_brush_path_len = 0;
|
int m_brush_path_len = 0;
|
||||||
int m_brush_thumb_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_path_len = 0;
|
||||||
|
int m_stencil_thumb_path_len = 0;
|
||||||
|
|
||||||
glm::vec4 m_tip_color{ 0, 0, 0, 1 };
|
glm::vec4 m_tip_color{ 0, 0, 0, 1 };
|
||||||
float m_tip_size = 0;
|
float m_tip_size = 0;
|
||||||
float m_tip_spacing = 0;
|
float m_tip_spacing = 0;
|
||||||
float m_tip_flow = 0;
|
float m_tip_flow = 0;
|
||||||
float m_tip_opacity = 0;
|
float m_tip_opacity = 0;
|
||||||
float m_tip_angle = 0;
|
float m_tip_angle = 0;
|
||||||
|
float m_tip_angle_delay = 0;
|
||||||
float m_tip_mix = 0;
|
float m_tip_mix = 0;
|
||||||
float m_tip_stencil = 0;
|
float m_tip_stencil = 0;
|
||||||
float m_tip_wet = 0;
|
float m_tip_wet = 0;
|
||||||
@@ -111,9 +119,6 @@ class NodePanelBrushPreset : public Node
|
|||||||
bool m_tip_angle_follow = false;
|
bool m_tip_angle_follow = false;
|
||||||
bool m_tip_flow_pressure = false;
|
bool m_tip_flow_pressure = false;
|
||||||
bool m_tip_size_pressure = false;
|
bool m_tip_size_pressure = false;
|
||||||
bool m_tip_hue_pressure = false;
|
|
||||||
bool m_tip_sat_pressure = false;
|
|
||||||
bool m_tip_val_pressure = false;
|
|
||||||
float m_jitter_scale = 0;
|
float m_jitter_scale = 0;
|
||||||
float m_jitter_angle = 0;
|
float m_jitter_angle = 0;
|
||||||
float m_jitter_spread = 0;
|
float m_jitter_spread = 0;
|
||||||
@@ -122,6 +127,24 @@ class NodePanelBrushPreset : public Node
|
|||||||
float m_jitter_sat = 0;
|
float m_jitter_sat = 0;
|
||||||
float m_jitter_val = 0;
|
float m_jitter_val = 0;
|
||||||
int m_blend_mode = 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;
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;
|
std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;
|
||||||
|
|||||||
@@ -26,10 +26,11 @@ void NodePanelStroke::update_controls()
|
|||||||
{
|
{
|
||||||
const auto& b = Canvas::I->m_current_brush;
|
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_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_spacing->m_value.x = glm::pow(b->m_tip_spacing, 1.f/2.f);
|
||||||
m_tip_flow->m_value.x = glm::pow(b->m_tip_flow, 1.f/2.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_opacity->m_value.x = b->m_tip_opacity;
|
||||||
m_tip_angle->m_value.x = b->m_tip_angle;
|
m_tip_angle->m_value.x = b->m_tip_angle;
|
||||||
|
m_tip_angle_delay->m_value.x = b->m_tip_angle_delay;
|
||||||
m_tip_stencil->m_value.x = b->m_tip_stencil;
|
m_tip_stencil->m_value.x = b->m_tip_stencil;
|
||||||
m_tip_wet->m_value.x = b->m_tip_wet;
|
m_tip_wet->m_value.x = b->m_tip_wet;
|
||||||
m_tip_noise->m_value.x = b->m_tip_noise;
|
m_tip_noise->m_value.x = b->m_tip_noise;
|
||||||
@@ -43,6 +44,28 @@ void NodePanelStroke::update_controls()
|
|||||||
m_tip_angle_follow->checked = b->m_tip_angle_follow;
|
m_tip_angle_follow->checked = b->m_tip_angle_follow;
|
||||||
m_tip_flow_pressure->checked = b->m_tip_flow_pressure;
|
m_tip_flow_pressure->checked = b->m_tip_flow_pressure;
|
||||||
m_tip_size_pressure->checked = b->m_tip_size_pressure;
|
m_tip_size_pressure->checked = b->m_tip_size_pressure;
|
||||||
|
|
||||||
|
m_tip_invert->checked = b->m_tip_invert;
|
||||||
|
m_tip_flipx->checked = b->m_tip_flipx;
|
||||||
|
m_tip_flipy->checked = b->m_tip_flipy;
|
||||||
|
m_tex_enabled->checked = b->m_tex_enabled;
|
||||||
|
m_dual_enabled->checked = b->m_dual_enabled;
|
||||||
|
m_dual_scatter_axis->checked = b->m_dual_scatter_axis;
|
||||||
|
m_dual_invert->checked = b->m_dual_invert;
|
||||||
|
m_dual_flipx->checked = b->m_dual_flipx;
|
||||||
|
m_dual_flipy->checked = b->m_dual_flipy;
|
||||||
|
m_dual_randflip->checked = b->m_dual_randflip;
|
||||||
|
m_tip_randflipx->checked = b->m_tip_randflipx;
|
||||||
|
m_tip_randflipy->checked = b->m_tip_randflipy;
|
||||||
|
|
||||||
|
m_dual_size->m_value.x = b->m_dual_size;
|
||||||
|
m_dual_spacing->m_value.x = b->m_dual_spacing;
|
||||||
|
m_dual_scatter->m_value.x = b->m_dual_scatter;
|
||||||
|
m_tip_aspect->m_value.x = b->m_tip_aspect;
|
||||||
|
|
||||||
|
m_blend_mode->set_index(b->m_blend_mode);
|
||||||
|
m_dual_blend_mode->set_index(b->m_dual_blend_mode);
|
||||||
|
|
||||||
m_preview->m_brush = b;
|
m_preview->m_brush = b;
|
||||||
m_preview->draw_stroke();
|
m_preview->draw_stroke();
|
||||||
}
|
}
|
||||||
@@ -71,17 +94,23 @@ void NodePanelStroke::init_controls()
|
|||||||
m_presets_popup->m_flood_events = true;
|
m_presets_popup->m_flood_events = true;
|
||||||
m_presets_popup->m_capture_children = false;
|
m_presets_popup->m_capture_children = false;
|
||||||
|
|
||||||
|
int br_idx = std::max(m_brush_popup->find_brush("Round-Hard"), 0);
|
||||||
|
// init main brush
|
||||||
auto b = std::make_shared<Brush>();
|
auto b = std::make_shared<Brush>();
|
||||||
int br_idx = m_brush_popup->find_brush("Round-Hard");
|
|
||||||
if (br_idx == -1)
|
|
||||||
br_idx = 0;
|
|
||||||
b->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
|
b->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
|
||||||
//b->load_stencil("data/paper.jpg");
|
|
||||||
b->m_tip_size = .1f;
|
b->m_tip_size = .1f;
|
||||||
b->m_tip_flow = .5f;
|
b->m_tip_flow = .5f;
|
||||||
b->m_tip_spacing = .1f;
|
b->m_tip_spacing = .1f;
|
||||||
b->m_tip_opacity = 1.f;
|
b->m_tip_opacity = 1.f;
|
||||||
Canvas::I->m_current_brush = b;
|
Canvas::I->m_current_brush = b;
|
||||||
|
// init dual brush
|
||||||
|
auto db = std::make_shared<Brush>();
|
||||||
|
db->load_texture(m_brush_popup->get_texture_path(br_idx), m_brush_popup->get_thumb_path(br_idx));
|
||||||
|
db->m_tip_size = .3f;
|
||||||
|
db->m_tip_flow = .5f;
|
||||||
|
db->m_tip_spacing = .1f;
|
||||||
|
db->m_tip_opacity = 1.f;
|
||||||
|
Canvas::I->m_dual_brush = db;
|
||||||
|
|
||||||
m_preset_thumb = find<NodeImage>("preset-thumb");
|
m_preset_thumb = find<NodeImage>("preset-thumb");
|
||||||
m_preset_thumb->m_use_mipmaps = true;
|
m_preset_thumb->m_use_mipmaps = true;
|
||||||
@@ -99,8 +128,10 @@ void NodePanelStroke::init_controls()
|
|||||||
tick->SetPosition(pos.x, pos.y + (m_preset_button->m_size.y - 32) * 0.5f);
|
tick->SetPosition(pos.x, pos.y + (m_preset_button->m_size.y - 32) * 0.5f);
|
||||||
tick->set_image("data/ui/popup-tick.png");
|
tick->set_image("data/ui/popup-tick.png");
|
||||||
root()->update();
|
root()->update();
|
||||||
if ((pos.y + m_presets_popup->m_size.y) > screen.y) pos.y = screen.y - m_presets_popup->m_size.y;
|
if ((pos.y + m_presets_popup->m_size.y) > screen.y)
|
||||||
if (pos.y < 0) pos.y = 0;
|
pos.y = screen.y - m_presets_popup->m_size.y;
|
||||||
|
if (pos.y < 0)
|
||||||
|
pos.y = 0;
|
||||||
m_presets_popup->SetPosition(pos.x + 16, pos.y);
|
m_presets_popup->SetPosition(pos.x + 16, pos.y);
|
||||||
m_presets_popup->mouse_capture();
|
m_presets_popup->mouse_capture();
|
||||||
root()->update();
|
root()->update();
|
||||||
@@ -111,7 +142,7 @@ void NodePanelStroke::init_controls()
|
|||||||
|
|
||||||
m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||||
// don't change some params
|
// don't change some params
|
||||||
//b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
|
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_color = Canvas::I->m_current_brush->m_tip_color;
|
||||||
*Canvas::I->m_current_brush = *b;
|
*Canvas::I->m_current_brush = *b;
|
||||||
m_preview->draw_stroke();
|
m_preview->draw_stroke();
|
||||||
@@ -125,8 +156,54 @@ void NodePanelStroke::init_controls()
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
m_dual_preset_thumb = find<NodeImage>("dual-preset-thumb");
|
||||||
|
m_dual_preset_thumb->m_use_mipmaps = true;
|
||||||
|
m_dual_preset_preview = find<NodeStrokePreview>("dual-preset-preview");
|
||||||
|
m_dual_preset_preview->m_brush = b;
|
||||||
|
m_dual_preset_preview->draw_stroke();
|
||||||
|
m_dual_preset_button = find<NodeButtonCustom>("dual-preset-button");
|
||||||
|
m_dual_preset_button->on_click = [this](Node*) {
|
||||||
|
auto screen = root()->m_size;
|
||||||
|
glm::vec2 pos = m_dual_preset_button->m_pos + glm::vec2(m_dual_preset_button->m_size.x, 0);
|
||||||
|
root()->add_child(m_presets_popup);
|
||||||
|
auto tick = root()->add_child<NodeImage>();
|
||||||
|
tick->SetPositioning(YGPositionTypeAbsolute);
|
||||||
|
tick->SetSize(16, 32);
|
||||||
|
tick->SetPosition(pos.x, pos.y + (m_dual_preset_button->m_size.y - 32) * 0.5f);
|
||||||
|
tick->set_image("data/ui/popup-tick.png");
|
||||||
|
root()->update();
|
||||||
|
if ((pos.y + m_presets_popup->m_size.y) > screen.y)
|
||||||
|
pos.y = screen.y - m_presets_popup->m_size.y;
|
||||||
|
if (pos.y < 0)
|
||||||
|
pos.y = 0;
|
||||||
|
m_presets_popup->SetPosition(pos.x + 16, pos.y);
|
||||||
|
m_presets_popup->mouse_capture();
|
||||||
|
root()->update();
|
||||||
|
|
||||||
|
m_presets_popup->on_popup_close = [this, tick](Node*) {
|
||||||
|
tick->destroy();
|
||||||
|
};
|
||||||
|
|
||||||
|
m_presets_popup->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||||
|
// don't change some params
|
||||||
|
b->m_tip_size = Canvas::I->m_current_brush->m_tip_size;
|
||||||
|
b->m_tip_color = { 0, 0, 0, 1 };
|
||||||
|
*Canvas::I->m_dual_brush = *b;
|
||||||
|
m_preview->draw_stroke();
|
||||||
|
m_dual_preset_preview->draw_stroke();
|
||||||
|
m_dual_brush_thumb->set_image(b->m_brush_thumb_path);
|
||||||
|
m_dual_preset_thumb->set_image(b->m_brush_thumb_path);
|
||||||
|
update_controls();
|
||||||
|
|
||||||
|
//m_presets_popup->mouse_release();
|
||||||
|
//m_presets_popup->parent->remove_child(m_presets_popup.get());
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
m_brush_thumb = find<NodeImage>("tip-change-thumb");
|
m_brush_thumb = find<NodeImage>("tip-change-thumb");
|
||||||
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
|
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
|
||||||
|
m_dual_brush_thumb = find<NodeImage>("dual-change-thumb");
|
||||||
|
m_dual_brush_thumb->set_image(m_brush_popup->get_thumb_path(br_idx));
|
||||||
|
|
||||||
m_brush_button = find<NodeButtonCustom>("tip-change");
|
m_brush_button = find<NodeButtonCustom>("tip-change");
|
||||||
m_brush_button->on_click = [this](Node*) {
|
m_brush_button->on_click = [this](Node*) {
|
||||||
@@ -139,8 +216,10 @@ void NodePanelStroke::init_controls()
|
|||||||
tick->SetPosition(pos.x, pos.y + (m_brush_button->m_size.y - 32) * 0.5f);
|
tick->SetPosition(pos.x, pos.y + (m_brush_button->m_size.y - 32) * 0.5f);
|
||||||
tick->set_image("data/ui/popup-tick.png");
|
tick->set_image("data/ui/popup-tick.png");
|
||||||
root()->update();
|
root()->update();
|
||||||
if ((pos.y + m_brush_popup->m_size.y) > screen.y) pos.y = screen.y - m_brush_popup->m_size.y;
|
if ((pos.y + m_brush_popup->m_size.y) > screen.y)
|
||||||
if (pos.y < 0) pos.y = 0;
|
pos.y = screen.y - m_brush_popup->m_size.y;
|
||||||
|
if (pos.y < 0)
|
||||||
|
pos.y = 0;
|
||||||
m_brush_popup->SetPosition(pos.x + 16, pos.y);
|
m_brush_popup->SetPosition(pos.x + 16, pos.y);
|
||||||
m_brush_popup->mouse_capture();
|
m_brush_popup->mouse_capture();
|
||||||
root()->update();
|
root()->update();
|
||||||
@@ -160,8 +239,11 @@ void NodePanelStroke::init_controls()
|
|||||||
|
|
||||||
m_preview = find<NodeStrokePreview>("canvas");
|
m_preview = find<NodeStrokePreview>("canvas");
|
||||||
m_blend_mode = find<NodeComboBox>("blend-mode");
|
m_blend_mode = find<NodeComboBox>("blend-mode");
|
||||||
m_blend_mode->on_select = [](Node*, int index) {
|
m_blend_mode->on_select = [this](Node*, int index) {
|
||||||
Canvas::I->m_current_brush->m_blend_mode = index;
|
Canvas::I->m_current_brush->m_blend_mode = index;
|
||||||
|
m_preview->draw_stroke();
|
||||||
|
if (on_stroke_change)
|
||||||
|
on_stroke_change(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
init_slider(m_tip_size, "tip-size", &Brush::m_tip_size);
|
init_slider(m_tip_size, "tip-size", &Brush::m_tip_size);
|
||||||
@@ -169,6 +251,7 @@ void NodePanelStroke::init_controls()
|
|||||||
init_slider(m_tip_flow, "tip-flow", &Brush::m_tip_flow);
|
init_slider(m_tip_flow, "tip-flow", &Brush::m_tip_flow);
|
||||||
init_slider(m_tip_opacity, "tip-opacity", &Brush::m_tip_opacity);
|
init_slider(m_tip_opacity, "tip-opacity", &Brush::m_tip_opacity);
|
||||||
init_slider(m_tip_angle, "tip-angle", &Brush::m_tip_angle);
|
init_slider(m_tip_angle, "tip-angle", &Brush::m_tip_angle);
|
||||||
|
init_slider(m_tip_angle_delay, "tip-angle-delay", &Brush::m_tip_angle_delay);
|
||||||
init_slider(m_tip_mix, "tip-mix", &Brush::m_tip_mix);
|
init_slider(m_tip_mix, "tip-mix", &Brush::m_tip_mix);
|
||||||
init_slider(m_tip_stencil, "tip-stencil", &Brush::m_tip_stencil);
|
init_slider(m_tip_stencil, "tip-stencil", &Brush::m_tip_stencil);
|
||||||
init_slider(m_tip_wet, "tip-wet", &Brush::m_tip_wet);
|
init_slider(m_tip_wet, "tip-wet", &Brush::m_tip_wet);
|
||||||
@@ -184,15 +267,47 @@ void NodePanelStroke::init_controls()
|
|||||||
init_slider(m_jitter_sat, "jitter-sat", &Brush::m_jitter_sat);
|
init_slider(m_jitter_sat, "jitter-sat", &Brush::m_jitter_sat);
|
||||||
init_slider(m_jitter_val, "jitter-val", &Brush::m_jitter_val);
|
init_slider(m_jitter_val, "jitter-val", &Brush::m_jitter_val);
|
||||||
m_curves[m_tip_size] = [](float v){ return glm::pow(v, 3.f); };
|
m_curves[m_tip_size] = [](float v){ return glm::pow(v, 3.f); };
|
||||||
m_curves[m_tip_spacing] = [](float v){ return glm::pow(v * 4.f, 2.f); };
|
m_curves[m_tip_spacing] = [](float v){ return glm::pow(v, 2.f); };
|
||||||
m_curves[m_tip_flow] = [](float v){ return glm::pow(v, 2.f); };
|
m_curves[m_tip_flow] = [](float v){ return glm::pow(v, 2.f); };
|
||||||
|
|
||||||
init_checkbox(m_tip_angle_follow, "tip-angle-follow", &Brush::m_tip_angle_follow);
|
init_checkbox(m_tip_angle_follow, "tip-angle-follow", &Brush::m_tip_angle_follow);
|
||||||
init_checkbox(m_tip_flow_pressure, "tip-flow-pressure", &Brush::m_tip_flow_pressure);
|
init_checkbox(m_tip_flow_pressure, "tip-flow-pressure", &Brush::m_tip_flow_pressure);
|
||||||
init_checkbox(m_tip_size_pressure, "tip-size-pressure", &Brush::m_tip_size_pressure);
|
init_checkbox(m_tip_size_pressure, "tip-size-pressure", &Brush::m_tip_size_pressure);
|
||||||
init_checkbox(m_tip_hue_pressure, "tip-hue-pressure", &Brush::m_tip_hue_pressure);
|
|
||||||
init_checkbox(m_tip_sat_pressure, "tip-sat-pressure", &Brush::m_tip_sat_pressure);
|
init_checkbox(m_tip_invert, "tip-invert", &Brush::m_tip_invert);
|
||||||
init_checkbox(m_tip_val_pressure, "tip-val-pressure", &Brush::m_tip_val_pressure);
|
init_checkbox(m_tip_flipx, "tip-flipx", &Brush::m_tip_flipx);
|
||||||
|
init_checkbox(m_tip_flipy, "tip-flipy", &Brush::m_tip_flipy);
|
||||||
|
init_checkbox(m_tex_enabled, "tex-enabled", &Brush::m_tex_enabled);
|
||||||
|
init_checkbox(m_dual_enabled, "dual-enabled", &Brush::m_dual_enabled);
|
||||||
|
init_checkbox(m_dual_scatter_axis, "dual-scatter-axis", &Brush::m_dual_scatter_axis);
|
||||||
|
init_checkbox(m_dual_invert, "dual-invert", &Brush::m_dual_invert);
|
||||||
|
init_checkbox(m_dual_flipx, "dual-flipx", &Brush::m_dual_flipx);
|
||||||
|
init_checkbox(m_dual_flipy, "dual-flipy", &Brush::m_dual_flipy);
|
||||||
|
init_checkbox(m_dual_randflip, "dual-randflip", &Brush::m_dual_randflip);
|
||||||
|
init_checkbox(m_tip_randflipx, "tip-randflipx", &Brush::m_tip_randflipx);
|
||||||
|
init_checkbox(m_tip_randflipy, "tip-randflipy", &Brush::m_tip_randflipy);
|
||||||
|
|
||||||
|
init_slider(m_dual_size, "dual-size", &Brush::m_dual_size);
|
||||||
|
init_slider(m_dual_spacing, "dual-spacing", &Brush::m_dual_spacing);
|
||||||
|
init_slider(m_dual_scatter, "dual-scatter", &Brush::m_dual_scatter);
|
||||||
|
init_slider(m_tip_aspect, "tip-aspect", &Brush::m_tip_aspect);
|
||||||
|
|
||||||
|
m_tip_aspect_reset = find<NodeButtonCustom>("tip-aspect-reset");
|
||||||
|
m_tip_aspect_reset->on_click = [this](Node*) {
|
||||||
|
m_tip_aspect->set_value(0.5);
|
||||||
|
Canvas::I->m_current_brush->m_tip_aspect = 0.5f;
|
||||||
|
m_preview->draw_stroke();
|
||||||
|
if (on_stroke_change)
|
||||||
|
on_stroke_change(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
m_dual_blend_mode = find<NodeComboBox>("blend-mode");
|
||||||
|
m_dual_blend_mode->on_select = [this](Node*, int index) {
|
||||||
|
Canvas::I->m_current_brush->m_dual_blend_mode = index;
|
||||||
|
m_preview->draw_stroke();
|
||||||
|
if (on_stroke_change)
|
||||||
|
on_stroke_change(this);
|
||||||
|
};
|
||||||
|
|
||||||
m_preview->m_brush = Canvas::I->m_current_brush;
|
m_preview->m_brush = Canvas::I->m_current_brush;
|
||||||
m_preview->draw_stroke();
|
m_preview->draw_stroke();
|
||||||
@@ -226,7 +341,6 @@ void NodePanelStroke::handle_slide(float Brush::* prop, Node* target, float valu
|
|||||||
{
|
{
|
||||||
auto curve = m_curves.find((NodeSliderH*)target);
|
auto curve = m_curves.find((NodeSliderH*)target);
|
||||||
Canvas::I->m_current_brush.get()->*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();
|
m_preview->draw_stroke();
|
||||||
if (on_stroke_change)
|
if (on_stroke_change)
|
||||||
on_stroke_change(this);
|
on_stroke_change(this);
|
||||||
@@ -243,7 +357,6 @@ void NodePanelStroke::init_checkbox(NodeCheckBox*& target, const char* id, bool
|
|||||||
void NodePanelStroke::handle_checkbox(bool Brush::* prop, Node *target, bool value)
|
void NodePanelStroke::handle_checkbox(bool Brush::* prop, Node *target, bool value)
|
||||||
{
|
{
|
||||||
Canvas::I->m_current_brush.get()->*prop = value;
|
Canvas::I->m_current_brush.get()->*prop = value;
|
||||||
m_preview->m_brush = Canvas::I->m_current_brush;
|
|
||||||
m_preview->draw_stroke();
|
m_preview->draw_stroke();
|
||||||
if (on_stroke_change)
|
if (on_stroke_change)
|
||||||
on_stroke_change(this);
|
on_stroke_change(this);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public:
|
|||||||
NodeSliderH* m_tip_flow;
|
NodeSliderH* m_tip_flow;
|
||||||
NodeSliderH* m_tip_opacity;
|
NodeSliderH* m_tip_opacity;
|
||||||
NodeSliderH* m_tip_angle;
|
NodeSliderH* m_tip_angle;
|
||||||
|
NodeSliderH* m_tip_angle_delay;
|
||||||
NodeSliderH* m_tip_mix;
|
NodeSliderH* m_tip_mix;
|
||||||
NodeSliderH* m_tip_stencil;
|
NodeSliderH* m_tip_stencil;
|
||||||
NodeSliderH* m_tip_wet;
|
NodeSliderH* m_tip_wet;
|
||||||
@@ -36,14 +37,35 @@ public:
|
|||||||
NodeCheckBox* m_tip_angle_follow;
|
NodeCheckBox* m_tip_angle_follow;
|
||||||
NodeCheckBox* m_tip_flow_pressure;
|
NodeCheckBox* m_tip_flow_pressure;
|
||||||
NodeCheckBox* m_tip_size_pressure;
|
NodeCheckBox* m_tip_size_pressure;
|
||||||
NodeCheckBox* m_tip_hue_pressure;
|
|
||||||
NodeCheckBox* m_tip_sat_pressure;
|
|
||||||
NodeCheckBox* m_tip_val_pressure;
|
|
||||||
NodeButtonCustom* m_brush_button;
|
NodeButtonCustom* m_brush_button;
|
||||||
NodeImage* m_brush_thumb;
|
NodeImage* m_brush_thumb;
|
||||||
|
NodeImage* m_dual_brush_thumb;
|
||||||
NodeImage* m_preset_thumb;
|
NodeImage* m_preset_thumb;
|
||||||
|
NodeImage* m_dual_preset_thumb;
|
||||||
NodeButtonCustom* m_preset_button;
|
NodeButtonCustom* m_preset_button;
|
||||||
|
NodeButtonCustom* m_dual_preset_button;
|
||||||
NodeStrokePreview* m_preset_preview;
|
NodeStrokePreview* m_preset_preview;
|
||||||
|
NodeStrokePreview* m_dual_preset_preview;
|
||||||
|
|
||||||
|
NodeCheckBox* m_tip_invert;
|
||||||
|
NodeCheckBox* m_tip_flipx;
|
||||||
|
NodeCheckBox* m_tip_flipy;
|
||||||
|
NodeCheckBox* m_tex_enabled;
|
||||||
|
NodeCheckBox* m_dual_enabled;
|
||||||
|
NodeCheckBox* m_dual_scatter_axis;
|
||||||
|
NodeCheckBox* m_dual_invert;
|
||||||
|
NodeCheckBox* m_dual_flipx;
|
||||||
|
NodeCheckBox* m_dual_flipy;
|
||||||
|
NodeCheckBox* m_dual_randflip;
|
||||||
|
NodeCheckBox* m_tip_randflipx;
|
||||||
|
NodeCheckBox* m_tip_randflipy;
|
||||||
|
NodeSliderH* m_dual_size;
|
||||||
|
NodeSliderH* m_dual_spacing;
|
||||||
|
NodeSliderH* m_dual_scatter;
|
||||||
|
NodeSliderH* m_tip_aspect;
|
||||||
|
NodeComboBox* m_dual_blend_mode;
|
||||||
|
NodeButtonCustom* m_tip_aspect_reset;
|
||||||
|
|
||||||
std::shared_ptr<NodePanelBrush> m_brush_popup;
|
std::shared_ptr<NodePanelBrush> m_brush_popup;
|
||||||
std::shared_ptr<NodePanelBrushPreset> m_presets_popup;
|
std::shared_ptr<NodePanelBrushPreset> m_presets_popup;
|
||||||
std::function<void(Node* target)> on_stroke_change;
|
std::function<void(Node* target)> on_stroke_change;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ void NodeText::clone_copy(Node* dest) const
|
|||||||
|
|
||||||
void NodeText::create()
|
void NodeText::create()
|
||||||
{
|
{
|
||||||
|
Node::create();
|
||||||
if (!m_font.empty())
|
if (!m_font.empty())
|
||||||
{
|
{
|
||||||
char font[64];
|
char font[64];
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ class NodeText : public Node
|
|||||||
public:
|
public:
|
||||||
TextMesh m_text_mesh;
|
TextMesh m_text_mesh;
|
||||||
std::string m_text;
|
std::string m_text;
|
||||||
std::string m_font;
|
std::string m_font = "arial";
|
||||||
glm::vec4 m_color{ 1, 1, 1, 1 };
|
glm::vec4 m_color{ 1, 1, 1, 1 };
|
||||||
int m_font_size;
|
int m_font_size = 11;
|
||||||
kFont font_id;
|
kFont font_id;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
virtual void clone_copy(Node* dest) const override;
|
virtual void clone_copy(Node* dest) const override;
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ Node* NodeViewport::clone_instantiate() const
|
|||||||
}
|
}
|
||||||
void NodeViewport::create()
|
void NodeViewport::create()
|
||||||
{
|
{
|
||||||
|
Node::create();
|
||||||
m_faces = std::make_unique<Plane>();
|
m_faces = std::make_unique<Plane>();
|
||||||
m_faces->create<1>(10, 10);
|
m_faces->create<1>(10, 10);
|
||||||
m_sampler = std::make_unique<Sampler>();
|
m_sampler = std::make_unique<Sampler>();
|
||||||
|
|||||||
@@ -113,6 +113,7 @@
|
|||||||
#include <glm/gtx/intersect.hpp>
|
#include <glm/gtx/intersect.hpp>
|
||||||
#include <glm/gtx/component_wise.hpp>
|
#include <glm/gtx/component_wise.hpp>
|
||||||
#include <glm/gtx/normal.hpp>
|
#include <glm/gtx/normal.hpp>
|
||||||
|
#include <glm/gtx/matrix_transform_2d.hpp>
|
||||||
|
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
#include <jpge.h>
|
#include <jpge.h>
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ RTT::RTT()
|
|||||||
|
|
||||||
RTT::~RTT()
|
RTT::~RTT()
|
||||||
{
|
{
|
||||||
//destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RTT::resize(int width, int height)
|
void RTT::resize(int width, int height)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ enum class kShaderUniform : uint16_t
|
|||||||
TexMix = const_hash("tex_mix"),
|
TexMix = const_hash("tex_mix"),
|
||||||
TexMixA = const_hash("tex_mix_alpha"),
|
TexMixA = const_hash("tex_mix_alpha"),
|
||||||
TexMask = const_hash("tex_mask"),
|
TexMask = const_hash("tex_mask"),
|
||||||
|
TexDual = const_hash("tex_dual"),
|
||||||
TexStroke = const_hash("tex_stroke"),
|
TexStroke = const_hash("tex_stroke"),
|
||||||
TexStencil = const_hash("tex_stencil"),
|
TexStencil = const_hash("tex_stencil"),
|
||||||
StencilOffset = const_hash("stencil_offset"),
|
StencilOffset = const_hash("stencil_offset"),
|
||||||
@@ -27,9 +28,11 @@ enum class kShaderUniform : uint16_t
|
|||||||
Resolution = const_hash("resolution"),
|
Resolution = const_hash("resolution"),
|
||||||
Highlight = const_hash("highlight"),
|
Highlight = const_hash("highlight"),
|
||||||
BlendMode = const_hash("blend_mode"),
|
BlendMode = const_hash("blend_mode"),
|
||||||
|
DualBlendMode = const_hash("blend_mode"),
|
||||||
Noise = const_hash("noise"),
|
Noise = const_hash("noise"),
|
||||||
Direction = const_hash("dir"),
|
Direction = const_hash("dir"),
|
||||||
UseFragCoordUV2 = const_hash("fragUV2"),
|
UseFragCoordUV2 = const_hash("fragUV2"),
|
||||||
|
UseDual = const_hash("use_dual"),
|
||||||
LightDir = const_hash("light_dir"),
|
LightDir = const_hash("light_dir"),
|
||||||
Mode = const_hash("mode"),
|
Mode = const_hash("mode"),
|
||||||
Ambient = const_hash("ambient"),
|
Ambient = const_hash("ambient"),
|
||||||
|
|||||||
13
src/util.cpp
13
src/util.cpp
@@ -14,6 +14,7 @@ std::vector<vertex_t> poly_remove_duplicate<vertex_t>(const std::vector<vertex_t
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// params {x, y} and {origin, size} form
|
||||||
bool point_in_rect(const glm::vec2& p, const glm::vec4& r)
|
bool point_in_rect(const glm::vec2& p, const glm::vec4& r)
|
||||||
{
|
{
|
||||||
return p.x > r.x && p.x < r.x+r.z && p.y > r.y && p.y < r.y+r.w;
|
return p.x > r.x && p.x < r.x+r.z && p.y > r.y && p.y < r.y+r.w;
|
||||||
@@ -45,6 +46,18 @@ glm::vec4 rect_union(glm::vec4 a, glm::vec4 b)
|
|||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// params and returns {min, max} form
|
||||||
|
glm::vec4 box_union(glm::vec4 a, glm::vec4 b)
|
||||||
|
{
|
||||||
|
return { glm::min(xy(a), xy(b)), glm::max(zw(a), zw(b)) };
|
||||||
|
}
|
||||||
|
|
||||||
|
// params and returns {min, max} form
|
||||||
|
glm::vec4 box_intersection(glm::vec4 a, glm::vec4 b)
|
||||||
|
{
|
||||||
|
return { glm::max(xy(a), xy(b)), glm::min(zw(a), zw(b)) };
|
||||||
|
}
|
||||||
|
|
||||||
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
||||||
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit, float& out_t)
|
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit, float& out_t)
|
||||||
{
|
{
|
||||||
|
|||||||
23
src/util.h
23
src/util.h
@@ -45,9 +45,16 @@ std::vector<T> poly_remove_duplicate(const std::vector<T>& v, const float toller
|
|||||||
template<>
|
template<>
|
||||||
std::vector<vertex_t> poly_remove_duplicate<vertex_t>(const std::vector<vertex_t>& v, const float tollerance);
|
std::vector<vertex_t> poly_remove_duplicate<vertex_t>(const std::vector<vertex_t>& v, const float tollerance);
|
||||||
|
|
||||||
|
// params {x, y} and {origin, size} form
|
||||||
bool point_in_rect(const glm::vec2& point, const glm::vec4& rect);
|
bool point_in_rect(const glm::vec2& point, const glm::vec4& rect);
|
||||||
|
// params and returns {origin, size} form
|
||||||
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b);
|
glm::vec4 rect_intersection(glm::vec4 a, glm::vec4 b);
|
||||||
|
// params and returns {origin, size} form
|
||||||
glm::vec4 rect_union(glm::vec4 a, glm::vec4 b);
|
glm::vec4 rect_union(glm::vec4 a, glm::vec4 b);
|
||||||
|
// params and returns {min, max} form
|
||||||
|
glm::vec4 box_union(glm::vec4 a, glm::vec4 b);
|
||||||
|
// params and returns {min, max} form
|
||||||
|
glm::vec4 box_intersection(glm::vec4 a, glm::vec4 b);
|
||||||
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
bool ray_intersect(glm::vec3 ray_origin, glm::vec3 ray_dir, glm::vec3 plane_origin,
|
||||||
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit, float& out_t);
|
glm::vec3 plane_normal, glm::vec3 plane_tangent, glm::vec3& out_hit, float& out_t);
|
||||||
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
|
bool segments_intersect(const glm::vec2& p0a, const glm::vec2& p0b,
|
||||||
@@ -78,15 +85,23 @@ inline glm::vec2 xy(const glm::vec3& v) { return glm::vec2(v.x, v.y); }
|
|||||||
|
|
||||||
void parallel_for(unsigned nb_elements, std::function<void(int i)> functor, bool use_threads = true);
|
void parallel_for(unsigned nb_elements, std::function<void(int i)> functor, bool use_threads = true);
|
||||||
|
|
||||||
template<typename T, int N> struct cbuffer
|
template<typename T> struct cbuffer
|
||||||
{
|
{
|
||||||
T m_vec[N];
|
std::unique_ptr<T[]> m_vec;
|
||||||
int m_capacity = 0;
|
int m_capacity = 0;
|
||||||
int m_count = 0;
|
int m_count = 0;
|
||||||
int m_index = 0;
|
int m_index = 0;
|
||||||
cbuffer()
|
cbuffer(int initial_capacity)
|
||||||
{
|
{
|
||||||
m_capacity = N;
|
m_capacity = initial_capacity;
|
||||||
|
m_index = 0;
|
||||||
|
m_count = 0;
|
||||||
|
m_vec = std::make_unique<T[]>(m_capacity);
|
||||||
|
}
|
||||||
|
void resize(int new_capacity)
|
||||||
|
{
|
||||||
|
m_capacity = new_capacity;
|
||||||
|
m_vec = std::make_unique<T[]>(m_capacity);
|
||||||
m_index = 0;
|
m_index = 0;
|
||||||
m_count = 0;
|
m_count = 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user