implement brush presets save and restore from file, fix stencil nullptr, limit preview stroke max size
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -46,3 +46,6 @@
|
|||||||
[submodule "libs/nanort"]
|
[submodule "libs/nanort"]
|
||||||
path = libs/nanort
|
path = libs/nanort
|
||||||
url = https://github.com/lighttransport/nanort.git
|
url = https://github.com/lighttransport/nanort.git
|
||||||
|
[submodule "libs/hash-library"]
|
||||||
|
path = libs/hash-library
|
||||||
|
url = https://github.com/stbrumme/hash-library
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
<LinkIncremental>true</LinkIncremental>
|
<LinkIncremental>true</LinkIncremental>
|
||||||
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;$(IncludePath)</IncludePath>
|
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;libs\hash-library;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
<LinkIncremental>false</LinkIncremental>
|
<LinkIncremental>false</LinkIncremental>
|
||||||
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;$(IncludePath)</IncludePath>
|
<IncludePath>libs\glm;libs\glew-2.0.0\include;libs\stb;libs\tinyxml2;libs\yoga;libs\curl-win\include;libs\jpeg;libs\wacom;libs\bugtrap-client\include;libs\poly2tri\poly2tri;libs\base64;libs\sqlite3;libs\openvr\headers;libs\nanort;libs\hash-library;$(IncludePath)</IncludePath>
|
||||||
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
<LibraryPath>libs\curl-win\lib\dll-$(Configuration)-$(PlatformShortName);libs\glew-2.0.0\lib\Release\$(Platform);libs\bugtrap-client\lib;libs\openvr\lib\win64;$(LibraryPath)</LibraryPath>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
@@ -169,6 +169,10 @@
|
|||||||
</PreBuildEvent>
|
</PreBuildEvent>
|
||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClCompile Include="libs\hash-library\md5.cpp">
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="libs\nanort\nanort.cc">
|
<ClCompile Include="libs\nanort\nanort.cc">
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">NotUsing</PrecompiledHeader>
|
||||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">NotUsing</PrecompiledHeader>
|
||||||
@@ -304,6 +308,7 @@
|
|||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<ClInclude Include="libs\hash-library\md5.h" />
|
||||||
<ClInclude Include="libs\nanort\nanort.h" />
|
<ClInclude Include="libs\nanort\nanort.h" />
|
||||||
<ClInclude Include="libs\sqlite3\sqlite3.h" />
|
<ClInclude Include="libs\sqlite3\sqlite3.h" />
|
||||||
<ClInclude Include="libs\sqlite3\sqlite3ext.h" />
|
<ClInclude Include="libs\sqlite3\sqlite3ext.h" />
|
||||||
|
|||||||
@@ -46,6 +46,9 @@
|
|||||||
<Filter Include="libs\nanort">
|
<Filter Include="libs\nanort">
|
||||||
<UniqueIdentifier>{be0c0053-abd8-4e2d-a294-7c54511b05a6}</UniqueIdentifier>
|
<UniqueIdentifier>{be0c0053-abd8-4e2d-a294-7c54511b05a6}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="libs\hash">
|
||||||
|
<UniqueIdentifier>{2a784067-6741-47a3-b668-cc45f2224286}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="src\app.cpp">
|
<ClCompile Include="src\app.cpp">
|
||||||
@@ -282,6 +285,9 @@
|
|||||||
<ClCompile Include="libs\nanort\nanort.cc">
|
<ClCompile Include="libs\nanort\nanort.cc">
|
||||||
<Filter>libs\nanort</Filter>
|
<Filter>libs\nanort</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="libs\hash-library\md5.cpp">
|
||||||
|
<Filter>libs\hash</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="src\app.h">
|
<ClInclude Include="src\app.h">
|
||||||
@@ -503,6 +509,9 @@
|
|||||||
<ClInclude Include="libs\nanort\nanort.h">
|
<ClInclude Include="libs\nanort\nanort.h">
|
||||||
<Filter>libs\nanort</Filter>
|
<Filter>libs\nanort</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="libs\hash-library\md5.h">
|
||||||
|
<Filter>libs\hash</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ResourceCompile Include="PanoPainter.rc">
|
<ResourceCompile Include="PanoPainter.rc">
|
||||||
|
|||||||
@@ -1127,7 +1127,7 @@ Here's a list of what's available in this release.
|
|||||||
<button-custom id="btn-stroke" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2">
|
<button-custom id="btn-stroke" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2">
|
||||||
<image path="data/ui/stroke.png" width="100%" height="100%" align="center" justify="flex-end"/>
|
<image path="data/ui/stroke.png" width="100%" height="100%" align="center" justify="flex-end"/>
|
||||||
</button-custom>
|
</button-custom>
|
||||||
<!--<button id="btn-brush-preset" width="50" height="50" margin="0 0 5 0" text="Preset" thickness="1" border-color=".1" pad="2"/>-->
|
<button id="btn-brush-preset" width="50" height="50" margin="0 0 5 0" text="Preset" thickness="1" border-color=".1" pad="2"/>
|
||||||
<!--
|
<!--
|
||||||
<button-custom id="btn-brush" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2">
|
<button-custom id="btn-brush" width="50" height="50" margin="0 0 5 0" thickness="1" border-color=".1" pad="2">
|
||||||
<image path="data/ui/brushes.png" width="100%" height="100%" align="center" justify="flex-end"/>
|
<image path="data/ui/brushes.png" width="100%" height="100%" align="center" justify="flex-end"/>
|
||||||
|
|||||||
1
libs/hash-library
Submodule
1
libs/hash-library
Submodule
Submodule libs/hash-library added at a8a88f8acb
@@ -132,19 +132,20 @@ void App::init_sidebar()
|
|||||||
// stroke->m_canvas->draw_stroke();
|
// stroke->m_canvas->draw_stroke();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
presets->on_brush_changed = [this](Node* target, int index) {
|
presets->on_brush_changed = [this](Node* target, std::shared_ptr<Brush>& b) {
|
||||||
auto b = presets->get_brush(index);
|
|
||||||
// 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;
|
||||||
stroke->m_preview->draw_stroke();
|
stroke->m_preview->draw_stroke();
|
||||||
|
stroke->m_brush_thumb->set_image(b->m_brush_thumb_path);
|
||||||
|
stroke->update_controls();
|
||||||
};
|
};
|
||||||
color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
color->on_color_changed = [this](Node* target, glm::vec4 color) {
|
||||||
Canvas::I->m_current_brush->m_tip_color = color;
|
Canvas::I->m_current_brush->m_tip_color = color;
|
||||||
};
|
};
|
||||||
stroke->on_brush_changed = [this](Node* target, const std::string& path) {
|
stroke->on_brush_changed = [this](Node* target, const std::string& path, const std::string& thumb) {
|
||||||
Canvas::I->m_current_brush->load_texture(path);
|
Canvas::I->m_current_brush->load_texture(path, thumb);
|
||||||
stroke->m_preview->draw_stroke();
|
stroke->m_preview->draw_stroke();
|
||||||
};
|
};
|
||||||
stroke->on_stencil_changed = [this](Node*target, const std::string& path) {
|
stroke->on_stencil_changed = [this](Node*target, const std::string& path) {
|
||||||
|
|||||||
@@ -86,7 +86,6 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
|||||||
else if (canvas->m_canvas->m_show_tmp && canvas->m_canvas->m_current_layer_idx == layer_index)
|
else if (canvas->m_canvas->m_show_tmp && canvas->m_canvas->m_current_layer_idx == layer_index)
|
||||||
{
|
{
|
||||||
sampler.bind(0);
|
sampler.bind(0);
|
||||||
auto& paper = *canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture;
|
|
||||||
ShaderManager::use(kShader::CompDraw);
|
ShaderManager::use(kShader::CompDraw);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||||
@@ -106,9 +105,13 @@ void App::vr_draw(const glm::mat4& proj, const glm::mat4& camera, const glm::mat
|
|||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
canvas->m_canvas->m_smask.m_rtt[plane_index].bindTexture();
|
canvas->m_canvas->m_smask.m_rtt[plane_index].bindTexture();
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
paper.bind();
|
if (canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_face_plane.draw_fill();
|
m_face_plane.draw_fill();
|
||||||
paper.unbind();
|
if (canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
canvas->m_canvas->m_current_stroke->m_brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
canvas->m_canvas->m_smask.m_rtt[plane_index].unbindTexture();
|
canvas->m_canvas->m_smask.m_rtt[plane_index].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
|||||||
@@ -135,12 +135,13 @@ StrokeSample Stroke::randomize_sample(const glm::vec3& pos, float pressure, floa
|
|||||||
|
|
||||||
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);
|
||||||
|
|
||||||
StrokeSample s;
|
StrokeSample s;
|
||||||
s.origin = pos;
|
s.origin = pos;
|
||||||
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_nor() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
s.angle = -curve_angle + (m_brush->m_tip_angle + rnd_nor() * m_brush->m_jitter_angle) * (float)(M_PI * 2.0);
|
||||||
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * 100.f);
|
s.pos = pos + (rnd_vec() * m_brush->m_jitter_spread * 100.f);
|
||||||
s.size = 800.f * m_brush->m_tip_size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
s.size = 800.f * size * (1.f - rnd_nor() * m_brush->m_jitter_scale) * size_dyn;
|
||||||
s.flow = m_brush->m_tip_flow * (1.f - rnd_nor() * m_brush->m_jitter_flow) * flow_dyn;
|
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 * (float)m_brush->m_tip_hue_pressure) + (rnd_nor() - 0.5f) * m_brush->m_jitter_hue, 0.f, 1.f);
|
||||||
@@ -215,7 +216,10 @@ void Stroke::add_point(glm::vec3 pos, float pressure)
|
|||||||
//pressure = m_pressure_buff.average();
|
//pressure = m_pressure_buff.average();
|
||||||
|
|
||||||
if (m_brush->m_tip_size_pressure)
|
if (m_brush->m_tip_size_pressure)
|
||||||
m_step = glm::max(m_brush->m_tip_spacing * m_brush->m_tip_size * pressure * 800.f, 1.f);
|
{
|
||||||
|
float 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);
|
||||||
|
}
|
||||||
|
|
||||||
float dist = m_keypoints.empty() ? m_step :
|
float dist = m_keypoints.empty() ? m_step :
|
||||||
m_keypoints.back().dist + glm::distance(m_keypoints.back().pos, pos);
|
m_keypoints.back().dist + glm::distance(m_keypoints.back().pos, pos);
|
||||||
@@ -238,28 +242,31 @@ void Stroke::start(const std::shared_ptr<Brush>& brush)
|
|||||||
m_hsv_jitter.clear();
|
m_hsv_jitter.clear();
|
||||||
m_last_kp = 0;
|
m_last_kp = 0;
|
||||||
m_dist = 0.f;
|
m_dist = 0.f;
|
||||||
m_brush = std::make_shared<Brush>(*brush);
|
m_brush = brush;
|
||||||
m_brush->m_tip_size *= 1.f / glm::tan(glm::radians(m_camera.fov * 0.5f));
|
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 * m_brush->m_tip_size * 800.f, 1.f);
|
m_step = glm::max(m_brush->m_tip_spacing * size * 800.f, 1.f);
|
||||||
prng.seed(0);
|
prng.seed(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Brush::load_texture(const std::string & path)
|
bool Brush::load_texture(const std::string& path, const std::string& thumb)
|
||||||
{
|
{
|
||||||
m_tip_texture = std::make_shared<Texture2D>();
|
m_tip_texture = std::make_shared<Texture2D>();
|
||||||
if (!m_tip_texture->load(path))
|
if (!m_tip_texture->load(path))
|
||||||
return false;
|
return false;
|
||||||
m_tip_texture->create_mipmaps();
|
m_tip_texture->create_mipmaps();
|
||||||
m_tip_texture->auto_destroy = true;
|
m_tip_texture->auto_destroy = true;
|
||||||
|
m_brush_path = path;
|
||||||
|
m_brush_thumb_path = thumb;
|
||||||
return true;
|
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>();
|
||||||
if (!m_stencil_texture->load(path))
|
if (!m_stencil_texture->load(path))
|
||||||
return false;
|
return false;
|
||||||
m_stencil_texture->create_mipmaps();
|
m_stencil_texture->create_mipmaps();
|
||||||
m_stencil_texture->auto_destroy = true;
|
m_stencil_texture->auto_destroy = true;
|
||||||
|
m_stencil_path = path;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,10 @@ class Brush
|
|||||||
public:
|
public:
|
||||||
Brush() = default;
|
Brush() = default;
|
||||||
Brush(const Brush& brush) = default;
|
Brush(const Brush& brush) = default;
|
||||||
int id = 0;
|
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
std::string m_brush_path;
|
||||||
|
std::string m_brush_thumb_path;
|
||||||
|
std::string m_stencil_path;
|
||||||
std::shared_ptr<Texture2D> m_tip_texture;
|
std::shared_ptr<Texture2D> m_tip_texture;
|
||||||
std::shared_ptr<Texture2D> m_stencil_texture;
|
std::shared_ptr<Texture2D> m_stencil_texture;
|
||||||
//uint16_t m_tex_id = 0;
|
//uint16_t m_tex_id = 0;
|
||||||
@@ -41,7 +43,7 @@ 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 load_texture(const std::string& path);
|
bool load_texture(const std::string& path, const std::string& thumb);
|
||||||
bool load_stencil(const std::string& path);
|
bool load_stencil(const std::string& path);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,6 +96,7 @@ public:
|
|||||||
float m_curve = 0;
|
float m_curve = 0;
|
||||||
float m_dist = 0;
|
float m_dist = 0;
|
||||||
float m_step = 0;
|
float m_step = 0;
|
||||||
|
float m_max_size = FLT_MAX;
|
||||||
Camera m_camera;
|
Camera m_camera;
|
||||||
std::shared_ptr<Brush> m_brush;
|
std::shared_ptr<Brush> m_brush;
|
||||||
cbuffer<float, 3> m_curve_angles;
|
cbuffer<float, 3> m_curve_angles;
|
||||||
|
|||||||
@@ -304,7 +304,6 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
|||||||
m_sampler.bind(0);
|
m_sampler.bind(0);
|
||||||
m_sampler.bind(1);
|
m_sampler.bind(1);
|
||||||
m_sampler.bind(2);
|
m_sampler.bind(2);
|
||||||
auto& paper = *m_current_stroke->m_brush->m_stencil_texture;
|
|
||||||
ShaderManager::use(kShader::CompDraw);
|
ShaderManager::use(kShader::CompDraw);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
//ShaderManager::u_int(kShaderUniform::TexA, 0);
|
//ShaderManager::u_int(kShaderUniform::TexA, 0);
|
||||||
@@ -326,9 +325,13 @@ void Canvas::stroke_draw_mix(const glm::vec2& bb_min, const glm::vec2& bb_sz)
|
|||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_smask.m_rtt[plane_index].bindTexture();
|
m_smask.m_rtt[plane_index].bindTexture();
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
paper.bind();
|
if (m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_current_stroke->m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_node->m_face_plane.draw_fill();
|
m_node->m_face_plane.draw_fill();
|
||||||
paper.unbind();
|
if (m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_current_stroke->m_brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_smask.m_rtt[plane_index].unbindTexture();
|
m_smask.m_rtt[plane_index].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
@@ -360,7 +363,6 @@ void Canvas::stroke_draw()
|
|||||||
const auto& m_brush = m_current_stroke->m_brush;
|
const auto& m_brush = m_current_stroke->m_brush;
|
||||||
auto samples = m_current_stroke->compute_samples();
|
auto samples = m_current_stroke->compute_samples();
|
||||||
auto& tex = *m_brush->m_tip_texture;
|
auto& tex = *m_brush->m_tip_texture;
|
||||||
auto& stencil = *m_brush->m_stencil_texture;
|
|
||||||
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
auto ortho_proj = glm::ortho(0.f, (float)m_width, 0.f, (float)m_height, -1.f, 1.f);
|
||||||
|
|
||||||
std::vector<vertex_t> B{
|
std::vector<vertex_t> B{
|
||||||
@@ -381,7 +383,11 @@ void Canvas::stroke_draw()
|
|||||||
//m_sampler_linear.bind(5);
|
//m_sampler_linear.bind(5);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
stencil.bind();
|
if (m_brush->m_stencil_texture)
|
||||||
|
m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
m_mixer.bindTexture();
|
m_mixer.bindTexture();
|
||||||
|
|
||||||
@@ -458,7 +464,10 @@ void Canvas::stroke_draw()
|
|||||||
//m_sampler_linear.bind(5);
|
//m_sampler_linear.bind(5);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
stencil.bind();
|
if (m_brush->m_stencil_texture)
|
||||||
|
m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
m_mixer.bindTexture();
|
m_mixer.bindTexture();
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
@@ -633,7 +642,8 @@ void Canvas::stroke_draw()
|
|||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
|
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
stencil.unbind();
|
if (m_brush->m_stencil_texture)
|
||||||
|
m_brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE3);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
m_mixer.unbindTexture();
|
m_mixer.unbindTexture();
|
||||||
|
|
||||||
@@ -846,8 +856,6 @@ void Canvas::stroke_commit()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto& paper = *m_current_stroke->m_brush->m_stencil_texture;
|
|
||||||
|
|
||||||
ShaderManager::use(kShader::CompDraw);
|
ShaderManager::use(kShader::CompDraw);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||||
@@ -867,9 +875,13 @@ 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);
|
||||||
paper.bind();
|
if (m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_current_stroke->m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_plane.draw_fill();
|
m_plane.draw_fill();
|
||||||
paper.unbind();
|
if (m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_current_stroke->m_brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
glActiveTexture(GL_TEXTURE2);
|
||||||
m_smask.m_rtt[i].unbindTexture();
|
m_smask.m_rtt[i].unbindTexture();
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ void CanvasModePen::on_MouseEvent(MouseEvent* me, glm::vec2& loc)
|
|||||||
if (m_dragging && m_resizing)
|
if (m_dragging && m_resizing)
|
||||||
{
|
{
|
||||||
auto diff = m_cur_pos - m_size_pos_start;
|
auto diff = m_cur_pos - m_size_pos_start;
|
||||||
canvas->m_current_brush->m_tip_size = m_size_value_start + diff.x * 0.001f;
|
canvas->m_current_brush->m_tip_size = glm::max(m_size_value_start + diff.x * 0.001f, 0.001f);
|
||||||
}
|
}
|
||||||
m_cur_pos = loc;
|
m_cur_pos = loc;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -201,7 +201,6 @@ void NodeCanvas::draw()
|
|||||||
else if(m_canvas->m_current_stroke && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
|
else if(m_canvas->m_current_stroke && m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
|
||||||
{
|
{
|
||||||
m_sampler.bind(0);
|
m_sampler.bind(0);
|
||||||
auto& paper = *m_canvas->m_current_stroke->m_brush->m_stencil_texture;
|
|
||||||
ShaderManager::use(kShader::CompDraw);
|
ShaderManager::use(kShader::CompDraw);
|
||||||
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
ShaderManager::u_int(kShaderUniform::Tex, 0);
|
||||||
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
ShaderManager::u_int(kShaderUniform::TexStroke, 1);
|
||||||
@@ -222,9 +221,13 @@ void NodeCanvas::draw()
|
|||||||
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);
|
glActiveTexture(GL_TEXTURE3);
|
||||||
paper.bind();
|
if (m_canvas->m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_canvas->m_current_stroke->m_brush->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_face_plane.draw_fill();
|
m_face_plane.draw_fill();
|
||||||
paper.unbind();
|
if (m_canvas->m_current_stroke->m_brush->m_stencil_texture)
|
||||||
|
m_canvas->m_current_stroke->m_brush->m_stencil_texture->unbind();
|
||||||
glActiveTexture(GL_TEXTURE2);
|
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);
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <Foundation/Foundation.h>
|
#include <Foundation/Foundation.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include "canvas.h"
|
||||||
|
#include "app.h"
|
||||||
|
|
||||||
Node* NodeButtonBrush::clone_instantiate() const
|
Node* NodeButtonBrush::clone_instantiate() const
|
||||||
{
|
{
|
||||||
@@ -186,7 +188,29 @@ Node* NodePanelBrushPreset::clone_instantiate() const
|
|||||||
void NodePanelBrushPreset::init()
|
void NodePanelBrushPreset::init()
|
||||||
{
|
{
|
||||||
init_template("tpl-panel-brush-preset");
|
init_template("tpl-panel-brush-preset");
|
||||||
|
m_container = find<NodeBorder>("brushes");
|
||||||
|
m_btn_add = find<NodeButtonCustom>("btn-add");
|
||||||
|
m_btn_add->on_click = [this] (Node*) {
|
||||||
|
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
|
||||||
|
m_container->add_child(brush);
|
||||||
|
brush->init();
|
||||||
|
brush->create();
|
||||||
|
brush->loaded();
|
||||||
|
brush->thumb_path = Canvas::I->m_current_brush->m_brush_thumb_path;
|
||||||
|
brush->high_path = Canvas::I->m_current_brush->m_brush_path;
|
||||||
|
brush->m_brush = std::make_shared<Brush>(*Canvas::I->m_current_brush);
|
||||||
|
brush->m_brush->m_tip_size = .05f;
|
||||||
|
brush->m_preview->m_brush = brush->m_brush;
|
||||||
|
brush->m_preview->draw_stroke();
|
||||||
|
brush->m_thumb->set_image(brush->m_brush->m_brush_thumb_path);
|
||||||
|
m_brushes.push_back(brush);
|
||||||
|
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
||||||
|
save();
|
||||||
|
};
|
||||||
|
|
||||||
|
restore();
|
||||||
|
|
||||||
|
/*
|
||||||
static auto icons = Asset::list_files("data/thumbs", true, ".*\\.png$");
|
static auto icons = Asset::list_files("data/thumbs", true, ".*\\.png$");
|
||||||
|
|
||||||
if ((m_container = find<NodeBorder>("brushes")))
|
if ((m_container = find<NodeBorder>("brushes")))
|
||||||
@@ -222,6 +246,7 @@ void NodePanelBrushPreset::init()
|
|||||||
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodePanelBrushPreset::handle_click(Node* target)
|
void NodePanelBrushPreset::handle_click(Node* target)
|
||||||
@@ -230,32 +255,132 @@ void NodePanelBrushPreset::handle_click(Node* target)
|
|||||||
return;
|
return;
|
||||||
if (m_current)
|
if (m_current)
|
||||||
m_current->m_selected = false;
|
m_current->m_selected = false;
|
||||||
m_current = (NodeButtonBrush*)target;
|
m_current = (NodeBrushPresetItem*)target;
|
||||||
m_current->m_selected = true;
|
m_current->m_selected = true;
|
||||||
if (on_brush_changed)
|
if (on_brush_changed)
|
||||||
on_brush_changed(this, m_current->m_brushID);
|
on_brush_changed(this, m_current->m_brush);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Brush> NodePanelBrushPreset::get_brush(int index) const
|
bool NodePanelBrushPreset::save()
|
||||||
{
|
{
|
||||||
auto& b = m_brushes[index]->m_brush;
|
auto path = App::I.data_path + "/presets.bin";
|
||||||
TextureManager::load(m_brushes[index]->high_path.c_str(), true);
|
if (FILE* fp = fopen(path.c_str(), "wb"))
|
||||||
//b->m_tex_id = m_brushes[index]->high_id;
|
{
|
||||||
return b;
|
header_t h;
|
||||||
|
h.count = m_brushes.size();
|
||||||
|
fwrite(&h, sizeof(h), 1, fp);
|
||||||
|
for (const auto& b : m_brushes)
|
||||||
|
{
|
||||||
|
item_t i;
|
||||||
|
i.m_name_len = b->m_brush->m_name.size();
|
||||||
|
i.m_brush_path_len = b->m_brush->m_brush_path.size();
|
||||||
|
i.m_brush_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_tip_color = b->m_brush->m_tip_color;
|
||||||
|
i.m_tip_size = b->m_brush->m_tip_size;
|
||||||
|
i.m_tip_spacing = b->m_brush->m_tip_spacing;
|
||||||
|
i.m_tip_flow = b->m_brush->m_tip_flow;
|
||||||
|
i.m_tip_opacity = b->m_brush->m_tip_opacity;
|
||||||
|
i.m_tip_angle = b->m_brush->m_tip_angle;
|
||||||
|
i.m_tip_mix = b->m_brush->m_tip_mix;
|
||||||
|
i.m_tip_stencil = b->m_brush->m_tip_stencil;
|
||||||
|
i.m_tip_wet = b->m_brush->m_tip_wet;
|
||||||
|
i.m_tip_noise = b->m_brush->m_tip_noise;
|
||||||
|
i.m_tip_hue = b->m_brush->m_tip_hue;
|
||||||
|
i.m_tip_sat = b->m_brush->m_tip_sat;
|
||||||
|
i.m_tip_val = b->m_brush->m_tip_val;
|
||||||
|
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_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_angle = b->m_brush->m_jitter_angle;
|
||||||
|
i.m_jitter_spread = b->m_brush->m_jitter_spread;
|
||||||
|
i.m_jitter_flow = b->m_brush->m_jitter_flow;
|
||||||
|
i.m_jitter_hue = b->m_brush->m_jitter_hue;
|
||||||
|
i.m_jitter_sat = b->m_brush->m_jitter_sat;
|
||||||
|
i.m_jitter_val = b->m_brush->m_jitter_val;
|
||||||
|
i.m_blend_mode = b->m_brush->m_blend_mode;
|
||||||
|
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_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_stencil_path.c_str(), 1, b->m_brush->m_stencil_path.size(), fp);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t NodePanelBrushPreset::get_texture_id(int index) const
|
bool NodePanelBrushPreset::restore()
|
||||||
{
|
{
|
||||||
TextureManager::load(m_brushes[index]->high_path.c_str(), true);
|
auto path = App::I.data_path + "/presets.bin";
|
||||||
return m_brushes[index]->high_id;
|
if (FILE* fp = fopen(path.c_str(), "rb"))
|
||||||
}
|
{
|
||||||
|
header_t h;
|
||||||
|
fread(&h, sizeof(h), 1, fp);
|
||||||
|
|
||||||
|
for (int k = 0; k < h.count; k++)
|
||||||
|
{
|
||||||
|
item_t i;
|
||||||
|
fread(&i, sizeof(i), 1, fp);
|
||||||
|
auto b = std::make_shared<Brush>();
|
||||||
|
b->m_tip_color = i.m_tip_color;
|
||||||
|
b->m_tip_size = i.m_tip_size;
|
||||||
|
b->m_tip_spacing = i.m_tip_spacing;
|
||||||
|
b->m_tip_flow = i.m_tip_flow;
|
||||||
|
b->m_tip_opacity = i.m_tip_opacity;
|
||||||
|
b->m_tip_angle = i.m_tip_angle;
|
||||||
|
b->m_tip_mix = i.m_tip_mix;
|
||||||
|
b->m_tip_stencil = i.m_tip_stencil;
|
||||||
|
b->m_tip_wet = i.m_tip_wet;
|
||||||
|
b->m_tip_noise = i.m_tip_noise;
|
||||||
|
b->m_tip_hue = i.m_tip_hue;
|
||||||
|
b->m_tip_sat = i.m_tip_sat;
|
||||||
|
b->m_tip_val = i.m_tip_val;
|
||||||
|
b->m_tip_angle_follow = i.m_tip_angle_follow;
|
||||||
|
b->m_tip_flow_pressure = i.m_tip_flow_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_angle = i.m_jitter_angle;
|
||||||
|
b->m_jitter_spread = i.m_jitter_spread;
|
||||||
|
b->m_jitter_flow = i.m_jitter_flow;
|
||||||
|
b->m_jitter_hue = i.m_jitter_hue;
|
||||||
|
b->m_jitter_sat = i.m_jitter_sat;
|
||||||
|
b->m_jitter_val = i.m_jitter_val;
|
||||||
|
b->m_blend_mode = i.m_blend_mode;
|
||||||
|
b->m_name.resize(i.m_name_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_stencil_path.resize(i.m_stencil_path_len);
|
||||||
|
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_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);
|
||||||
|
|
||||||
std::string NodePanelBrushPreset::get_texture_path(int index) const
|
b->load_texture(b->m_brush_path, b->m_brush_thumb_path);
|
||||||
{
|
|
||||||
return m_brushes[index]->high_path;
|
|
||||||
}
|
|
||||||
|
|
||||||
int NodePanelBrushPreset::get_brush_id(int index) const
|
NodeBrushPresetItem* brush = new NodeBrushPresetItem;
|
||||||
{
|
m_container->add_child(brush);
|
||||||
return m_brushes[index]->m_brushID;
|
brush->init();
|
||||||
|
brush->create();
|
||||||
|
brush->loaded();
|
||||||
|
brush->thumb_path = b->m_brush_thumb_path;
|
||||||
|
brush->high_path = b->m_brush_path;
|
||||||
|
brush->m_brush = b;
|
||||||
|
brush->m_brush->m_tip_size = .05f;
|
||||||
|
brush->m_preview->m_brush = b;
|
||||||
|
brush->m_preview->draw_stroke();
|
||||||
|
brush->m_thumb->set_image(brush->m_brush->m_brush_thumb_path);
|
||||||
|
m_brushes.push_back(brush);
|
||||||
|
brush->on_click = std::bind(&NodePanelBrushPreset::handle_click, this, std::placeholders::_1);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,11 +46,9 @@ public:
|
|||||||
class NodeBrushPresetItem : public NodeButtonCustom
|
class NodeBrushPresetItem : public NodeButtonCustom
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int m_brushID;
|
|
||||||
std::shared_ptr<Brush> m_brush;
|
std::shared_ptr<Brush> m_brush;
|
||||||
std::string high_path;
|
std::string high_path;
|
||||||
std::string thumb_path;
|
std::string thumb_path;
|
||||||
uint16_t high_id;
|
|
||||||
bool m_selected = false;
|
bool m_selected = false;
|
||||||
NodeStrokePreview* m_preview;
|
NodeStrokePreview* m_preview;
|
||||||
NodeImage* m_thumb;
|
NodeImage* m_thumb;
|
||||||
@@ -62,16 +60,57 @@ public:
|
|||||||
class NodePanelBrushPreset : public Node
|
class NodePanelBrushPreset : public Node
|
||||||
{
|
{
|
||||||
std::vector<NodeBrushPresetItem*> m_brushes;
|
std::vector<NodeBrushPresetItem*> m_brushes;
|
||||||
NodeButtonBrush* m_current = nullptr;
|
NodeBrushPresetItem* m_current = nullptr;
|
||||||
Node* m_container;
|
Node* m_container;
|
||||||
|
NodeButtonCustom* m_btn_add;
|
||||||
|
NodeButtonCustom* m_btn_save;
|
||||||
|
struct header_t {
|
||||||
|
char magic[4]{ 'P', 'P', 'P', 'R' };
|
||||||
|
uint16_t version = 0;
|
||||||
|
uint16_t count = 0;
|
||||||
|
};
|
||||||
|
struct item_t {
|
||||||
|
int m_name_len;
|
||||||
|
int m_brush_path_len;
|
||||||
|
int m_brush_thumb_path_len;
|
||||||
|
int m_stencil_path_len;
|
||||||
|
//std::shared_ptr<Texture2D> m_tip_texture;
|
||||||
|
//std::shared_ptr<Texture2D> m_stencil_texture;
|
||||||
|
glm::vec4 m_tip_color{ 0, 0, 0, 1 };
|
||||||
|
float m_tip_size = 0;
|
||||||
|
float m_tip_spacing = 0;
|
||||||
|
float m_tip_flow = 0;
|
||||||
|
float m_tip_opacity = 0;
|
||||||
|
float m_tip_angle = 0;
|
||||||
|
float m_tip_mix = 0;
|
||||||
|
float m_tip_stencil = 0;
|
||||||
|
float m_tip_wet = 0;
|
||||||
|
float m_tip_noise = 0;
|
||||||
|
float m_tip_hue = 0;
|
||||||
|
float m_tip_sat = 0;
|
||||||
|
float m_tip_val = 0;
|
||||||
|
bool m_tip_angle_follow = false;
|
||||||
|
bool m_tip_flow_pressure = false;
|
||||||
|
bool m_tip_size_pressure = false;
|
||||||
|
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_angle = 0;
|
||||||
|
float m_jitter_spread = 0;
|
||||||
|
float m_jitter_flow = 0;
|
||||||
|
float m_jitter_hue = 0;
|
||||||
|
float m_jitter_sat = 0;
|
||||||
|
float m_jitter_val = 0;
|
||||||
|
int m_blend_mode = 0;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
std::function<void(Node* target, int id)> on_brush_changed;
|
std::function<void(Node* target, std::shared_ptr<Brush>& brush)> on_brush_changed;
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
virtual void init() override;
|
virtual void init() override;
|
||||||
void handle_click(Node* target);
|
void handle_click(Node* target);
|
||||||
uint16_t get_texture_id(int index) const;
|
|
||||||
std::string get_texture_path(int index) const;
|
|
||||||
std::shared_ptr<Brush> get_brush(int index) const;
|
std::shared_ptr<Brush> get_brush(int index) const;
|
||||||
int get_brush_id(int index) const;
|
bool save();
|
||||||
|
bool restore();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ void NodePanelStroke::init_controls()
|
|||||||
|
|
||||||
auto b = std::make_shared<Brush>();
|
auto b = std::make_shared<Brush>();
|
||||||
int br_idx = m_brush_popup->find_brush("Round-Hard");
|
int br_idx = m_brush_popup->find_brush("Round-Hard");
|
||||||
b->load_texture(m_brush_popup->get_texture_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->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;
|
||||||
@@ -83,7 +83,7 @@ void NodePanelStroke::init_controls()
|
|||||||
|
|
||||||
m_brush_popup->on_brush_changed = [this](Node*, int index) {
|
m_brush_popup->on_brush_changed = [this](Node*, int index) {
|
||||||
if (on_brush_changed)
|
if (on_brush_changed)
|
||||||
on_brush_changed(this, m_brush_popup->get_texture_path(index));
|
on_brush_changed(this, m_brush_popup->get_texture_path(index), m_brush_popup->get_thumb_path(index));
|
||||||
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(index));
|
m_brush_thumb->set_image(m_brush_popup->get_thumb_path(index));
|
||||||
m_brush_popup->mouse_release();
|
m_brush_popup->mouse_release();
|
||||||
m_brush_popup->parent->remove_child(m_brush_popup.get());
|
m_brush_popup->parent->remove_child(m_brush_popup.get());
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
std::shared_ptr<NodePanelBrush> m_brush_popup;
|
std::shared_ptr<NodePanelBrush> m_brush_popup;
|
||||||
std::function<void(Node* target)> on_stroke_change;
|
std::function<void(Node* target)> on_stroke_change;
|
||||||
std::function<void(Node* target, const std::string& path)> on_stencil_changed;
|
std::function<void(Node* target, const std::string& path)> on_stencil_changed;
|
||||||
std::function<void(Node* target, const std::string& path)> on_brush_changed;
|
std::function<void(Node* target, const std::string& path, const std::string& thumb)> on_brush_changed;
|
||||||
std::map<NodeSliderH*, std::function<float(float)>> m_curves;
|
std::map<NodeSliderH*, std::function<float(float)>> m_curves;
|
||||||
|
|
||||||
virtual Node* clone_instantiate() const override;
|
virtual Node* clone_instantiate() const override;
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ void NodeStrokePreview::draw_stroke()
|
|||||||
glm::mat4 proj = glm::ortho<float>(0, (float)m_rtt.getWidth(), 0, (float)m_rtt.getHeight(), -1, 1);
|
glm::mat4 proj = glm::ortho<float>(0, (float)m_rtt.getWidth(), 0, (float)m_rtt.getHeight(), -1, 1);
|
||||||
|
|
||||||
const auto& b = m_brush;
|
const auto& b = m_brush;
|
||||||
|
m_stroke.m_max_size = 0.1f;
|
||||||
m_stroke.m_camera.fov = Canvas::I->m_cam_fov;
|
m_stroke.m_camera.fov = Canvas::I->m_cam_fov;
|
||||||
m_stroke.m_camera.rot = Canvas::I->m_cam_rot;
|
m_stroke.m_camera.rot = Canvas::I->m_cam_rot;
|
||||||
m_stroke.reset();
|
m_stroke.reset();
|
||||||
@@ -80,9 +81,11 @@ void NodeStrokePreview::draw_stroke()
|
|||||||
tex.bind();
|
tex.bind();
|
||||||
m_sampler_brush.bind(0);
|
m_sampler_brush.bind(0);
|
||||||
|
|
||||||
auto& stencil = *b->m_stencil_texture;
|
|
||||||
glActiveTexture(GL_TEXTURE1);
|
glActiveTexture(GL_TEXTURE1);
|
||||||
stencil.bind();
|
if (b->m_stencil_texture)
|
||||||
|
b->m_stencil_texture->bind();
|
||||||
|
else
|
||||||
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
m_sampler.bind(1);
|
m_sampler.bind(1);
|
||||||
|
|
||||||
if (true)
|
if (true)
|
||||||
@@ -138,6 +141,9 @@ void NodeStrokePreview::draw()
|
|||||||
|
|
||||||
void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
|
void NodeStrokePreview::handle_resize(glm::vec2 old_size, glm::vec2 new_size)
|
||||||
{
|
{
|
||||||
|
if (old_size == new_size)
|
||||||
|
return;
|
||||||
|
|
||||||
float pad = 30.f;
|
float pad = 30.f;
|
||||||
new_size *= root()->m_zoom;
|
new_size *= root()->m_zoom;
|
||||||
float w = new_size.x;
|
float w = new_size.x;
|
||||||
|
|||||||
Reference in New Issue
Block a user