diff --git a/data/layout.xml b/data/layout.xml
index 3ac5fe8..cbbd31b 100644
--- a/data/layout.xml
+++ b/data/layout.xml
@@ -243,6 +243,49 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -687,7 +730,6 @@
-->
-
-
+
diff --git a/engine.xcodeproj/project.pbxproj b/engine.xcodeproj/project.pbxproj
index 53523e9..60f30d7 100644
--- a/engine.xcodeproj/project.pbxproj
+++ b/engine.xcodeproj/project.pbxproj
@@ -170,6 +170,12 @@
ADBC8C561FAFD0530094B339 /* app_cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C511FAFD0360094B339 /* app_cloud.cpp */; };
ADBC8C571FAFD05A0094B339 /* node_dialog_cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C521FAFD0370094B339 /* node_dialog_cloud.cpp */; };
ADBC8C581FAFD05A0094B339 /* node_dialog_cloud.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADBC8C521FAFD0370094B339 /* node_dialog_cloud.cpp */; };
+ ADC0EB3D1FBDC748004079BB /* node_colorwheel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB3B1FBDC748004079BB /* node_colorwheel.cpp */; };
+ ADC0EB3E1FBDC748004079BB /* node_colorwheel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB3B1FBDC748004079BB /* node_colorwheel.cpp */; };
+ ADC0EB3F1FBDC748004079BB /* node_colorwheel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB3B1FBDC748004079BB /* node_colorwheel.cpp */; };
+ ADC0EB421FC36E88004079BB /* node_dialog_picker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB401FC36E88004079BB /* node_dialog_picker.cpp */; };
+ ADC0EB431FC36E88004079BB /* node_dialog_picker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB401FC36E88004079BB /* node_dialog_picker.cpp */; };
+ ADC0EB441FC36E88004079BB /* node_dialog_picker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC0EB401FC36E88004079BB /* node_dialog_picker.cpp */; };
ADC6F4621F3AFF2C004177FA /* node_dialog_layer_rename.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC6F4611F3AFA2B004177FA /* node_dialog_layer_rename.cpp */; };
ADC6F4631F3AFF2D004177FA /* node_dialog_layer_rename.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC6F4611F3AFA2B004177FA /* node_dialog_layer_rename.cpp */; };
ADC6F4641F3AFF2E004177FA /* node_dialog_layer_rename.cpp in Sources */ = {isa = PBXBuildFile; fileRef = ADC6F4611F3AFA2B004177FA /* node_dialog_layer_rename.cpp */; };
@@ -368,6 +374,10 @@
ADBC8C501FAFD0360094B339 /* node_dialog_cloud.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = node_dialog_cloud.h; sourceTree = ""; };
ADBC8C511FAFD0360094B339 /* app_cloud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_cloud.cpp; sourceTree = ""; };
ADBC8C521FAFD0370094B339 /* node_dialog_cloud.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = node_dialog_cloud.cpp; sourceTree = ""; };
+ ADC0EB3B1FBDC748004079BB /* node_colorwheel.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = node_colorwheel.cpp; sourceTree = ""; };
+ ADC0EB3C1FBDC748004079BB /* node_colorwheel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = node_colorwheel.h; sourceTree = ""; };
+ ADC0EB401FC36E88004079BB /* node_dialog_picker.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = node_dialog_picker.cpp; sourceTree = ""; };
+ ADC0EB411FC36E88004079BB /* node_dialog_picker.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = node_dialog_picker.h; sourceTree = ""; };
ADC6F4601F3AFA2A004177FA /* node_dialog_layer_rename.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = node_dialog_layer_rename.h; sourceTree = ""; };
ADC6F4611F3AFA2B004177FA /* node_dialog_layer_rename.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = node_dialog_layer_rename.cpp; sourceTree = ""; };
ADC6F4651F3E66FA004177FA /* app_dialogs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = app_dialogs.cpp; sourceTree = ""; };
@@ -479,6 +489,8 @@
AD10635A1EC7ADFA002A525F /* node_checkbox.h */,
AD10635B1EC7ADFA002A525F /* node_color_quad.cpp */,
AD10635C1EC7ADFA002A525F /* node_color_quad.h */,
+ ADC0EB3B1FBDC748004079BB /* node_colorwheel.cpp */,
+ ADC0EB3C1FBDC748004079BB /* node_colorwheel.h */,
AD74030D1FB9D0C0004ACFCC /* node_combobox.cpp */,
AD74030C1FB9D0BF004ACFCC /* node_combobox.h */,
ADBC8C471FAE7CC20094B339 /* node_dialog_browse.cpp */,
@@ -489,6 +501,8 @@
AD10635E1EC7ADFA002A525F /* node_dialog_open.h */,
ADC6F4611F3AFA2B004177FA /* node_dialog_layer_rename.cpp */,
ADC6F4601F3AFA2A004177FA /* node_dialog_layer_rename.h */,
+ ADC0EB401FC36E88004079BB /* node_dialog_picker.cpp */,
+ ADC0EB411FC36E88004079BB /* node_dialog_picker.h */,
AD10635F1EC7ADFA002A525F /* node_icon.cpp */,
AD1063601EC7ADFA002A525F /* node_icon.h */,
AD1063611EC7ADFA002A525F /* node_image_texture.cpp */,
@@ -829,10 +843,12 @@
AD0E5CCE1ECC72AD00C35669 /* node_text.cpp in Sources */,
AD0E5CDC1ECC72AD00C35669 /* image.cpp in Sources */,
AD0E5CE01ECC72AD00C35669 /* shader.cpp in Sources */,
+ ADC0EB3F1FBDC748004079BB /* node_colorwheel.cpp in Sources */,
AD0E5CDD1ECC72AD00C35669 /* log.cpp in Sources */,
AD0E5CD61ECC72AD00C35669 /* bezier.cpp in Sources */,
AD0E5CB61ECC72AD00C35669 /* Yoga.c in Sources */,
ADE4911D1F86E65E00FB8E92 /* shapes.cc in Sources */,
+ ADC0EB441FC36E88004079BB /* node_dialog_picker.cpp in Sources */,
AD0E5CC51ECC72AD00C35669 /* node_panel_color.cpp in Sources */,
AD0E5CD71ECC72AD00C35669 /* brush.cpp in Sources */,
AD7403101FB9D0D4004ACFCC /* node_combobox.cpp in Sources */,
@@ -893,6 +909,7 @@
AD10638F1EC7ADFA002A525F /* node_settings.cpp in Sources */,
AD10638D1EC7ADFA002A525F /* node_panel_stroke.cpp in Sources */,
AD1063841EC7ADFA002A525F /* node_color_quad.cpp in Sources */,
+ ADC0EB421FC36E88004079BB /* node_dialog_picker.cpp in Sources */,
AD1063881EC7ADFA002A525F /* node_image.cpp in Sources */,
AD58E0761E3421F2006ACC15 /* YGNodeList.c in Sources */,
AD744B6E1EBC9EF800B66E30 /* canvas_modes.cpp in Sources */,
@@ -915,6 +932,7 @@
AD0E11A31ECA61B500CDA6BB /* jpge.cpp in Sources */,
AD1063811EC7ADFA002A525F /* node_button.cpp in Sources */,
ADB1C3DA1EA3A156009A65BD /* event.cpp in Sources */,
+ ADC0EB3D1FBDC748004079BB /* node_colorwheel.cpp in Sources */,
AD4C08D91E89BD0F0051D85F /* asset.cpp in Sources */,
AD1063851EC7ADFA002A525F /* node_dialog_open.cpp in Sources */,
AD58E0681E2A7741006ACC15 /* image.cpp in Sources */,
@@ -964,6 +982,7 @@
ADD7D29F1EBF9E1C00D5A897 /* app.cpp in Sources */,
AD1063A41EC7AE92002A525F /* node_panel_layer.cpp in Sources */,
AD1063AA1EC7AE92002A525F /* node_text_input.cpp in Sources */,
+ ADC0EB3E1FBDC748004079BB /* node_colorwheel.cpp in Sources */,
ADD6AFD81F94DEB000E92461 /* node_progress_bar.cpp in Sources */,
AD0E119B1ECA215600CDA6BB /* node_scroll.cpp in Sources */,
ADD7D2941EBF9E1C00D5A897 /* asset.cpp in Sources */,
@@ -992,6 +1011,7 @@
ADD7D2A21EBF9E1C00D5A897 /* util.cpp in Sources */,
ADD7D2791EBF9AE300D5A897 /* GameViewController.m in Sources */,
ADD7D26F1EBF9AE300D5A897 /* main.m in Sources */,
+ ADC0EB431FC36E88004079BB /* node_dialog_picker.cpp in Sources */,
ADD7D2A01EBF9E1C00D5A897 /* image.cpp in Sources */,
ADD7D2A11EBF9E1C00D5A897 /* texture.cpp in Sources */,
AD0E119C1ECA215600CDA6BB /* app_events.cpp in Sources */,
diff --git a/engine/app.cpp b/engine/app.cpp
index 356b511..54ed681 100644
--- a/engine/app.cpp
+++ b/engine/app.cpp
@@ -242,7 +242,7 @@ void App::update(float dt)
//glViewport(0, 0, (GLsizei)width, (GLsizei)height);
//glClear(GL_COLOR_BUFFER_BIT);
-#ifdef _WIN32
+#if _WIN32 || __OSX__
layout.reload();
#endif
if (auto* main = layout[main_id])
@@ -260,7 +260,7 @@ void App::update(float dt)
auto pix = ui::Canvas::I->m_current_brush.m_tip_color;
auto hsv = convert_rgb2hsv(glm::vec3(pix[0], pix[1], pix[2]));
color->m_hue->set_value(hsv.x);
- color->m_quad->set_value(1.f - hsv.y, 1.f - hsv.z);
+ color->m_quad->set_value(hsv.y, 1.f - hsv.z);
auto observer = [this](Node* n)
{
diff --git a/engine/app_shaders.cpp b/engine/app_shaders.cpp
index 37ff329..9a7ca53 100644
--- a/engine/app_shaders.cpp
+++ b/engine/app_shaders.cpp
@@ -180,11 +180,47 @@ void App::initShaders()
"uniform mediump vec4 col;"
"in mediump vec3 uv;"
"out mediump vec4 frag;"
- "void main(){"
- " mediump vec4 gradient_x = mix(col, vec4(1.0, 1.0, 1.0, 1.0), uv.x);"
- " frag = mix(gradient_x, vec4(0.0, 0.0, 0.0, 1.0), uv.y);"
+ "mediump vec3 rgb2hsv(mediump vec3 c) {"
+ " mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);"
+ " mediump vec4 p = mix(vec4(c.bg, k.wz), vec4(c.gb, k.xy), step(c.b, c.g));"
+ " mediump vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));"
+ " mediump float d = q.x - min(q.w, q.y);"
+ " mediump float e = 1.0e-10;"
+ " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);"
+ "}"
+ "mediump vec3 hsv2rgb(mediump vec3 c) {"
+ " mediump vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);"
+ " mediump vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);"
+ " return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);"
+ "}"
+ "void main() {"
+ " mediump float hue = rgb2hsv(col.rgb).x;"
+ " frag = vec4(hsv2rgb(vec3(hue, uv.x, 1.0 - uv.y)), 1.0);"
"}";
-
+ // COLOR TRI
+ static const char* shader_color_tri_f =
+ SHADER_VERSION
+ "uniform mediump vec4 col;" // in HSV
+ "in mediump vec3 uv;"
+ "out mediump vec4 frag;"
+ "mediump vec3 rgb2hsv(mediump vec3 c) {"
+ " mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);"
+ " mediump vec4 p = mix(vec4(c.bg, k.wz), vec4(c.gb, k.xy), step(c.b, c.g));"
+ " mediump vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));"
+ " mediump float d = q.x - min(q.w, q.y);"
+ " mediump float e = 1.0e-10;"
+ " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);"
+ "}"
+ "mediump vec3 hsv2rgb(mediump vec3 c) {"
+ " mediump vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);"
+ " mediump vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);"
+ " return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);"
+ "}"
+ "void main() {"
+ " mediump float sat = tan(atan(uv.y, uv.x)) *.5 + .5;"
+ " frag = vec4(hsv2rgb(vec3(col.r, sat, uv.x)), 1.0);"
+ "}";
+
// HUE
static const char* shader_color_hue_v =
SHADER_VERSION
@@ -199,15 +235,24 @@ void App::initShaders()
static const char* shader_color_hue_f =
SHADER_VERSION
"uniform mediump vec4 col;"
+ "uniform bool dir;" // 0:horizontal, 1:vertical
"in mediump vec3 uv;"
"out mediump vec4 frag;"
+ "mediump vec3 rgb2hsv(mediump vec3 c) {"
+ " mediump vec4 k = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);"
+ " mediump vec4 p = mix(vec4(c.bg, k.wz), vec4(c.gb, k.xy), step(c.b, c.g));"
+ " mediump vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));"
+ " mediump float d = q.x - min(q.w, q.y);"
+ " mediump float e = 1.0e-10;"
+ " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);"
+ "}"
"mediump vec3 hsv2rgb(mediump vec3 c) {"
" mediump vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);"
" mediump vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);"
" return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);"
"}"
"void main(){"
- " frag = vec4(hsv2rgb(vec3(uv.y, 1.0, 1.0)), 1.0);"
+ " frag = vec4(hsv2rgb(vec3(dir?uv.y:uv.x, 1.0, 1.0)), 1.0);"
"}";
// FONT
@@ -373,6 +418,27 @@ void App::initShaders()
" frag = vec4(col.rgb, a);"
"}";
+ // VERTEX COLOR
+ static const char* shader_vertcol_v =
+ SHADER_VERSION
+ "uniform mat4 mvp;"
+ "in vec4 pos;"
+ "in vec4 col;"
+ "out vec4 c;"
+ "void main(){"
+ " c = col;"
+ " gl_Position = mvp * pos;"
+ " gl_PointSize = 5.0;"
+ "}";
+ static const char* shader_vertcol_f =
+ SHADER_VERSION
+ "in mediump vec4 c;"
+ "out mediump vec4 frag;"
+ "void main(){"
+ " frag = c;"
+ "}";
+
+
LOG("initializing shaders");
if (!ShaderManager::create(kShader::Texture, shader_v, shader_f))
LOG("Failed to create shader Texture");
@@ -388,6 +454,8 @@ void App::initShaders()
LOG("Failed to create shader Color");
if (!ShaderManager::create(kShader::ColorQuad, shader_color_quad_v, shader_color_quad_f))
LOG("Failed to create shader ColorQuad");
+ if (!ShaderManager::create(kShader::ColorTri, shader_color_quad_v, shader_color_tri_f))
+ LOG("Failed to create shader ColorTri");
if (!ShaderManager::create(kShader::ColorHue, shader_color_hue_v, shader_color_hue_f))
LOG("Failed to create shader ColorHue");
if (!ShaderManager::create(kShader::UVs, shader_v, shader_uv_f))
@@ -404,6 +472,8 @@ void App::initShaders()
LOG("Failed to create shader Equirect");
if (!ShaderManager::create(kShader::BrushStroke, shader_stroke_inst_v, shader_stroke_inst_f))
LOG("Failed to create shader BrushStroke");
+ if (!ShaderManager::create(kShader::VertexColor, shader_vertcol_v, shader_vertcol_f))
+ LOG("Failed to create shader VertexColor");
LOG("shaders initialized");
}
diff --git a/engine/asset.cpp b/engine/asset.cpp
index 7d06d9d..b228342 100644
--- a/engine/asset.cpp
+++ b/engine/asset.cpp
@@ -117,6 +117,17 @@ std::vector Asset::list_files(std::string folder, bool is_asset, co
return names;
}
+std::string Asset::absolute(const std::string& path)
+{
+#ifdef __APPLE__
+ NSString* bundle_path = [[NSBundle mainBundle] resourcePath];
+ std::string base = [bundle_path cStringUsingEncoding:1];
+ return base + "/" + path;
+#else
+ return path;
+#endif
+}
+
bool Asset::open(const char* path)
{
//LOG("Asset::open %s", path);
diff --git a/engine/asset.h b/engine/asset.h
index 174a719..1fcc440 100644
--- a/engine/asset.h
+++ b/engine/asset.h
@@ -10,6 +10,7 @@ public:
static std::vector list_files(std::string folder, bool is_asset, const std::string& filter_regex);
static bool exist(std::string path, bool is_asset);
static bool delete_file(const std::string& path);
+ static std::string absolute(const std::string& path);
std::string m_current_path;
FILE* m_fp = nullptr;
diff --git a/engine/brush.h b/engine/brush.h
index 00ad76b..b2dcc24 100644
--- a/engine/brush.h
+++ b/engine/brush.h
@@ -10,7 +10,7 @@ public:
int id = 0;
std::string m_name;
uint16_t m_tex_id = 0;
- glm::vec4 m_tip_color;
+ glm::vec4 m_tip_color{1, 0, 0, 1};
float m_tip_size = 0;
float m_tip_spacing = 0;
float m_tip_flow = 0;
diff --git a/engine/canvas.cpp b/engine/canvas.cpp
index 74c1dac..02b5a55 100644
--- a/engine/canvas.cpp
+++ b/engine/canvas.cpp
@@ -1324,6 +1324,7 @@ void ui::Canvas::project_open_thread(std::string file_path)
l.destroy();
m_layers.clear();
m_order.clear();
+ resize(m_width, m_height);
App::I.async_end();
std::vector tmp_order;
diff --git a/engine/layout.cpp b/engine/layout.cpp
index 59687a1..fd59fca 100644
--- a/engine/layout.cpp
+++ b/engine/layout.cpp
@@ -8,10 +8,10 @@
bool LayoutManager::load(const char* path)
{
-
-#if _WIN32
+ auto abs_path = Asset::absolute(path);
+#if _WIN32 || __OSX__
struct stat tmp_info;
- if (stat(path, &tmp_info) != 0)
+ if (stat(abs_path.c_str(), &tmp_info) != 0)
return false;
if (tmp_info.st_mtime <= m_file_info.st_mtime)
return false;
diff --git a/engine/node.cpp b/engine/node.cpp
index 8249566..ef1ac11 100644
--- a/engine/node.cpp
+++ b/engine/node.cpp
@@ -28,6 +28,8 @@
#include "node_dialog_browse.h"
#include "node_dialog_cloud.h"
#include "node_combobox.h"
+#include "node_colorwheel.h"
+#include "node_dialog_picker.h"
void Node::async_start()
{
@@ -381,6 +383,7 @@ Node::~Node()
void Node::SetWidth(float value)
{
YGNodeStyleSetWidth(y_node, value);
+ m_size.x = value;
}
void Node::SetWidthP(float value)
@@ -391,6 +394,7 @@ void Node::SetWidthP(float value)
void Node::SetHeight(float value)
{
YGNodeStyleSetHeight(y_node, value);
+ m_size.y = value;
}
void Node::SetHeightP(float value)
@@ -401,11 +405,13 @@ void Node::SetHeightP(float value)
void Node::SetSize(float w, float h)
{
SetWidth(w); SetHeight(h);
+ m_size = {w, h};
}
void Node::SetSize(glm::vec2 value)
{
SetWidth(value.x); SetHeight(value.y);
+ m_size = value;
}
void Node::SetPadding(float t, float r, float b, float l)
@@ -428,12 +434,14 @@ glm::vec4 Node::GetPadding() const
void Node::SetPosition(const glm::vec2 pos)
{
SetPosition(pos.x, pos.y);
+ m_pos = pos;
}
void Node::SetPosition(float l, float t)
{
YGNodeStyleSetPosition(y_node, YGEdgeTop, t);
YGNodeStyleSetPosition(y_node, YGEdgeLeft, l);
+ m_pos = {l, t};
}
void Node::SetPosition(float l, float t, float r, float b)
@@ -818,6 +826,8 @@ void Node::load_internal(const tinyxml2::XMLElement* x_node)
CASE(kWidget::DialogBrowseItem, NodeDialogBrowseItem);
CASE(kWidget::DialogCloud, NodeDialogCloud);
CASE(kWidget::DialogCloudItem, NodeDialogCloudItem);
+ CASE(kWidget::ColorWheel, NodeColorWheel);
+ CASE(kWidget::ColorPicker, NodeColorPicker);
#undef CASE
case kWidget::Ref:
{
diff --git a/engine/node.h b/engine/node.h
index eb66f5b..fa47b58 100644
--- a/engine/node.h
+++ b/engine/node.h
@@ -76,6 +76,8 @@ enum class kWidget : uint16_t
DialogBrowseItem = const_hash("dialog-browse-item"),
DialogCloud = const_hash("dialog-cloud"),
DialogCloudItem = const_hash("dialog-cloud-item"),
+ ColorWheel = const_hash("colorwheel"),
+ ColorPicker = const_hash("color-picker"),
};
class Node
diff --git a/engine/node_canvas.cpp b/engine/node_canvas.cpp
index dbdbb79..1895e49 100644
--- a/engine/node_canvas.cpp
+++ b/engine/node_canvas.cpp
@@ -143,7 +143,7 @@ void NodeCanvas::draw()
}
else if(m_canvas->m_show_tmp && m_canvas->m_current_layer_idx == layer_index)
{
- m_sampler.bind(0);
+ m_sampler_linear.bind(0);
auto& paper = TextureManager::get(const_hash("data/paper.jpg"));
ui::ShaderManager::use(kShader::CompDraw);
ui::ShaderManager::u_int(kShaderUniform::Tex, 0);
diff --git a/engine/node_color_quad.cpp b/engine/node_color_quad.cpp
index 9e7f131..875c979 100644
--- a/engine/node_color_quad.cpp
+++ b/engine/node_color_quad.cpp
@@ -27,7 +27,7 @@ void NodeColorQuad::init()
void NodeColorQuad::set_value(float x, float y)
{
- auto sz = GetSize();
+ auto sz = m_size;
auto pos = glm::clamp(glm::vec2(x, y) * sz, { 0, 0 }, sz);
m_picker->SetPosition(pos - m_picker->GetSize() * .5f);
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
@@ -45,7 +45,7 @@ kEventResult NodeColorQuad::handle_event(Event* e)
m_old_value = m_value;
dragging = true;
mouse_capture();
- auto sz = GetSize();
+ auto sz = m_size;
auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz);
m_picker->SetPosition(pos - m_picker->GetSize() * .5f);
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
@@ -60,7 +60,7 @@ kEventResult NodeColorQuad::handle_event(Event* e)
case kEventType::MouseMove:
if (dragging)
{
- auto sz = GetSize();
+ auto sz = m_size;
auto pos = glm::clamp(((MouseEvent*)e)->m_pos - m_pos, { 0, 0 }, sz);
m_picker->SetPosition(pos - m_picker->GetSize() * .5f);
m_value = pos / glm::max({ 1,1 }, sz); // avoid div0
diff --git a/engine/node_color_quad.h b/engine/node_color_quad.h
index b178073..395c159 100644
--- a/engine/node_color_quad.h
+++ b/engine/node_color_quad.h
@@ -3,11 +3,11 @@
class NodeColorQuad : public NodeBorder
{
- NodeBorder* m_picker;
+ NodeBorder* m_picker{nullptr};
bool dragging = false;
public:
- glm::vec2 m_value;
- glm::vec2 m_old_value;
+ glm::vec2 m_value{0.f};
+ glm::vec2 m_old_value{0.f};
std::function on_value_changed;
virtual Node* clone_instantiate() const override;
virtual void clone_finalize(Node* dest) const override;
diff --git a/engine/node_colorwheel.cpp b/engine/node_colorwheel.cpp
new file mode 100644
index 0000000..8bb023e
--- /dev/null
+++ b/engine/node_colorwheel.cpp
@@ -0,0 +1,77 @@
+#include "pch.h"
+#include "node_colorwheel.h"
+#include "shader.h"
+
+Node* NodeColorWheel::clone_instantiate() const
+{
+ return new NodeColorWheel;
+}
+
+void NodeColorWheel::clone_finalize(Node* dest) const
+{
+ NodeColorWheel* n = (NodeColorWheel*)dest;
+ n->init_controls();
+}
+
+void NodeColorWheel::init()
+{
+ //init_template("color-picker");
+ init_controls();
+}
+
+void NodeColorWheel::init_controls()
+{
+}
+
+void NodeColorWheel::loaded()
+{
+ m_circle.create<64>(.5, .4, ui::Circle::kUVMapping::Tube);
+ m_cur_hue.create<16>(.05);
+
+ struct vertex_t { glm::vec4 pos; glm::vec2 uvs; glm::vec4 col; };
+ std::vector vertices;
+ float l = 0.4;
+ vertices.push_back({{glm::cos(4.f/3.f*glm::pi())*l,glm::sin(4.f/3.f*glm::pi())*l,0,1},{1,-1},{1,1,1,1}});
+ vertices.push_back({{glm::cos(2.f/3.f*glm::pi())*l,glm::sin(2.f/3.f*glm::pi())*l,0,1},{0,0},{0,0,0,1}});
+ vertices.push_back({{l,0,0,1},{1,1},{1,0,0,1}});
+
+ glGenBuffers(1, &buffers);
+ glBindBuffer(GL_ARRAY_BUFFER, buffers);
+ glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(vertex_t), vertices.data(), GL_STATIC_DRAW);
+ glBindBuffer(GL_ARRAY_BUFFER, 0);
+
+ glGenVertexArrays(1, &arrays);
+ glBindVertexArray(arrays);
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
+ glEnableVertexAttribArray(2);
+ glBindBuffer(GL_ARRAY_BUFFER, buffers);
+ glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)0);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, uvs));
+ glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, sizeof(vertex_t), (GLvoid*)offsetof(vertex_t, col));
+ glBindVertexArray(0);
+}
+
+void NodeColorWheel::draw()
+{
+ using namespace ui;
+
+ glDisable(GL_BLEND);
+ ShaderManager::use(kShader::ColorHue);
+ ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
+ ShaderManager::u_int(kShaderUniform::Direction, 0); // set horizontal
+ m_circle.draw_fill();
+
+ ShaderManager::use(kShader::ColorTri);
+ ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
+ ShaderManager::u_vec4(kShaderUniform::Col, {1, 0, 0, 1});
+ GLenum type = GL_TRIANGLES;
+ glBindVertexArray(arrays);
+ glDrawArrays(type, 0, 3);
+ glBindVertexArray(0);
+
+ ShaderManager::use(kShader::Color);
+ ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp * glm::eulerAngleZ(glm::radians(45.f)) * glm::translate(glm::vec3(.45,0,0)));
+ ShaderManager::u_vec4(kShaderUniform::Col, {1, 1, 1, 1});
+ m_cur_hue.draw_stroke();
+}
diff --git a/engine/node_colorwheel.h b/engine/node_colorwheel.h
new file mode 100644
index 0000000..12d8162
--- /dev/null
+++ b/engine/node_colorwheel.h
@@ -0,0 +1,22 @@
+#pragma once
+#include "util.h"
+#include "node.h"
+#include "shape.h"
+#include "node_slider.h"
+
+class NodeColorWheel : public Node
+{
+public:
+ ui::Circle m_circle;
+ ui::Circle m_cur_hue;
+ GLuint m_tri_vbo;
+ GLuint m_tri_vao;
+ GLuint buffers;
+ GLuint arrays;
+ virtual Node* clone_instantiate() const override;
+ virtual void clone_finalize(Node* dest) const;
+ virtual void init() override;
+ virtual void loaded() override;
+ virtual void draw() override;
+ void init_controls();
+};
diff --git a/engine/node_combobox.cpp b/engine/node_combobox.cpp
index 8aa7480..f640226 100644
--- a/engine/node_combobox.cpp
+++ b/engine/node_combobox.cpp
@@ -57,8 +57,11 @@ void NodeComboBox::loaded()
float offset = 0;
for (int i = 0; i <= m_selected_child_index; i++)
offset += (m_data[i] == "-") ? 5.f : 30.f;
-
+ float height = m_items.size() * 30.f + (m_data.size() - m_items.size()) * 5.f; // add items and separators
glm::vec2 pos = m_pos + glm::vec2(0, m_size.y - offset);
+ auto screen = root()->m_size;
+ if ((pos.y + height) > screen.y) pos.y = screen.y - height;
+ if (pos.y < 0) pos.y = 0;
popup->SetPositioning(YGPositionTypeAbsolute);
popup->SetPosition(pos.x, pos.y);
popup->SetSize(m_size.x, YGUndefined);
diff --git a/engine/node_dialog_picker.cpp b/engine/node_dialog_picker.cpp
new file mode 100644
index 0000000..cd919c8
--- /dev/null
+++ b/engine/node_dialog_picker.cpp
@@ -0,0 +1,55 @@
+#include "pch.h"
+#include "log.h"
+#include "util.h"
+#include "canvas.h"
+#include "node_dialog_picker.h"
+
+Node* NodeColorPicker::clone_instantiate() const
+{
+ return new NodeColorPicker;
+}
+
+void NodeColorPicker::clone_finalize(Node* dest) const
+{
+ auto n = static_cast(dest);
+ n->init_controls();
+}
+
+void NodeColorPicker::init()
+{
+ auto n = (NodeColorPicker*)init_template("color-picker");
+ n->clone_copy(this);
+ init_controls();
+}
+
+void NodeColorPicker::draw()
+{
+ NodeBorder::draw();
+ glm::vec3 rgb = glm::vec3(ui::Canvas::I->m_current_brush.m_tip_color);
+ glm::vec3 hsv = convert_rgb2hsv(rgb);
+ m_slider_h->set_value(hsv.x);
+ m_slider_s->set_value(hsv.y);
+ m_slider_v->set_value(hsv.z);
+ m_slider_r->set_value(rgb.x);
+ m_slider_g->set_value(rgb.y);
+ m_slider_b->set_value(rgb.z);
+}
+
+void NodeColorPicker::init_controls()
+{
+ m_slider_h = find("hsv-h");
+ m_slider_s = find("hsv-s");
+ m_slider_v = find("hsv-v");
+ m_slider_r = find("rgb-r");
+ m_slider_g = find("rgb-g");
+ m_slider_b = find("rgb-b");
+ m_wheel = find("wheel");
+}
+
+glm::vec4 NodeColorPicker::get_hsv() const
+{
+ float h = m_slider_h->get_value();
+ float s = m_slider_s->get_value();
+ float v = m_slider_v->get_value();
+ return glm::vec4(h, s, v, 1.f);
+}
diff --git a/engine/node_dialog_picker.h b/engine/node_dialog_picker.h
new file mode 100644
index 0000000..040a8bf
--- /dev/null
+++ b/engine/node_dialog_picker.h
@@ -0,0 +1,26 @@
+#include "node.h"
+#include "node_border.h"
+#include "node_slider.h"
+#include "node_colorwheel.h"
+
+class NodeColorPicker : public NodeBorder
+{
+public:
+ NodeSliderH* m_slider_h;
+ NodeSliderH* m_slider_s;
+ NodeSliderH* m_slider_v;
+ NodeSliderH* m_slider_r;
+ NodeSliderH* m_slider_g;
+ NodeSliderH* m_slider_b;
+ NodeColorWheel* m_wheel;
+ glm::vec4 m_rgb;
+ glm::vec4 m_hsv;
+
+ virtual Node* clone_instantiate() const override;
+ //virtual void clone_copy(Node* dest) const override;
+ virtual void clone_finalize(Node* dest) const override;
+ virtual void init() override;
+ virtual void draw() override;
+ void init_controls();
+ glm::vec4 get_hsv() const;
+};
diff --git a/engine/node_panel_color.cpp b/engine/node_panel_color.cpp
index 7766530..80318e1 100644
--- a/engine/node_panel_color.cpp
+++ b/engine/node_panel_color.cpp
@@ -25,16 +25,16 @@ void NodePanelColor::init_controls()
m_hue = find("hue");
m_hue->on_hue_changed = [this](Node*, glm::vec4 hue_color) {
m_base_color = m_quad->m_color = hue_color;
- auto x = glm::mix(m_base_color, glm::vec4(1, 1, 1, 1), m_cursor.x);
- m_color = glm::mix(x, glm::vec4(0, 0, 0, 1), m_cursor.y);
+ float hue = convert_rgb2hsv(m_base_color).x;
+ m_color = glm::vec4(convert_hsv2rgb(glm::vec3(hue, m_cursor.x, 1.f-m_cursor.y)), 1.f);
if (on_color_changed)
on_color_changed(this, m_color);
};
m_quad->on_value_changed = [this](Node*, glm::vec2 pos)
{
- auto x = glm::mix(m_base_color, glm::vec4(1, 1, 1, 1), pos.x);
- m_color = glm::mix(x, glm::vec4(0, 0, 0, 1), pos.y);
m_cursor = pos;
+ float hue = convert_rgb2hsv(m_base_color).x;
+ m_color = glm::vec4(convert_hsv2rgb(glm::vec3(hue, m_cursor.x, 1.f-m_cursor.y)), 1.f);
if (on_color_changed)
on_color_changed(this, m_color);
};
diff --git a/engine/node_slider.cpp b/engine/node_slider.cpp
index d402bb3..9593138 100644
--- a/engine/node_slider.cpp
+++ b/engine/node_slider.cpp
@@ -152,6 +152,7 @@ void NodeSliderHue::draw()
ui::ShaderManager::use(kShader::ColorHue);
ui::ShaderManager::u_mat4(kShaderUniform::MVP, m_mvp);
//ui::ShaderManager::u_vec4(kShaderUniform::Col, m_color);
+ ui::ShaderManager::u_int(kShaderUniform::Direction, 1); // set vertical
m_plane.draw_fill();
NodeBorder::m_color = glm::vec4(0);
NodeSliderH::draw();
diff --git a/engine/shader.cpp b/engine/shader.cpp
index 4f33879..98cf023 100644
--- a/engine/shader.cpp
+++ b/engine/shader.cpp
@@ -66,7 +66,8 @@ bool Shader::create(const char* vertex, const char* fragment)
glBindAttribLocation(ps, 0, "pos");
glBindAttribLocation(ps, 1, "uvs");
-
+ glBindAttribLocation(ps, 2, "col");
+
glLinkProgram(ps);
glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
diff --git a/engine/shader.h b/engine/shader.h
index 9a5af83..9a1e297 100644
--- a/engine/shader.h
+++ b/engine/shader.h
@@ -25,12 +25,14 @@ enum class kShaderUniform : uint16_t
Highlight = const_hash("highlight"),
BlendMode = const_hash("blend_mode"),
Noise = const_hash("noise"),
+ Direction = const_hash("dir"),
};
enum class kShader : uint16_t
{
Color = const_hash("color"),
ColorQuad = const_hash("color-quad"),
+ ColorTri = const_hash("color-tri"),
ColorHue = const_hash("color-hue"),
Texture = const_hash("texture"),
TextureAlpha= const_hash("texture-alpha"),
@@ -44,6 +46,7 @@ enum class kShader : uint16_t
Checkerboard= const_hash("checkerboard"),
Equirect = const_hash("equirect"),
BrushStroke = const_hash("brush-stroke"),
+ VertexColor = const_hash("vertex-color"),
};
class Shader