cgv
Loading...
Searching...
No Matches
color_map_editor.h
1#pragma once
2
3#include <cgv/render/color_map.h>
4#include <cgv/render/texture.h>
5#include <cgv_app/themed_canvas_overlay.h>
6#include <cgv_app/color_selector.h>
7#include <cgv_g2d/draggable_collection.h>
8#include <cgv_g2d/generic_2d_renderer.h>
9#include <cgv_g2d/generic_2d_render_data.h>
10#include <cgv_g2d/msdf_text_geometry.h>
11
12#include "lib_begin.h"
13
14namespace cgv {
15
16namespace app {
17
19protected:
21 int padding;
22 int total_height;
23
24 // dependent members
25 int color_editor_height;
26 int opacity_editor_height;
27 cgv::g2d::irect color_handles_rect;
28 cgv::g2d::irect color_editor_rect;
29 cgv::g2d::irect opacity_editor_rect;
30
31 void update(const ivec2& parent_size, bool color_and_opacity) {
32
33 int content_height = total_height - 10 - 2 * padding;
34 if(color_and_opacity) {
35 color_editor_height = static_cast<int>(floor(0.15f * static_cast<float>(content_height)));
36 color_editor_height = cgv::math::clamp(color_editor_height, 4, 80);
37 opacity_editor_height = content_height - color_editor_height - 1;
38 } else {
39 color_editor_height = content_height;
40 opacity_editor_height = 0;
41 }
42
43 int y_off = padding;
44
45 color_handles_rect.position = ivec2(padding, 20);
46 color_handles_rect.size = ivec2(parent_size.x() - 2 * padding, 0);
47
48 // move 10px up to clear some space for the color handles rect
49 y_off += 10;
50
51 color_editor_rect.position = ivec2(padding, y_off);
52 color_editor_rect.size = ivec2(parent_size.x() - 2 * padding, color_editor_height);
53
54 y_off += color_editor_height + 1; // plus 1px border
55
56 opacity_editor_rect.position = ivec2(padding, y_off);
57 opacity_editor_rect.size = ivec2(parent_size.x() - 2 * padding, opacity_editor_height);
58 }
59 } layout;
60
61 struct color_point : public cgv::g2d::draggable {
62 static const float default_width;
63 static const float default_height;
64 float val;
65 rgb col;
66
67 color_point() {
68 size = vec2(default_width, default_height);
69 position_is_center = true;
70 constraint_reference = CR_CENTER;
71 }
72
73 void update_val(const layout_attributes& la) {
74 vec2 p = position - la.color_handles_rect.position;
75 val = p.x() / la.color_handles_rect.size.x();
76 val = cgv::math::clamp(val, 0.0f, 1.0f);
77 }
78
79 void update_pos(const layout_attributes& la) {
80 val = cgv::math::clamp(val, 0.0f, 1.0f);
81 float t = val;
82 position.x() = static_cast<float>(la.color_handles_rect.position.x()) + t * la.color_handles_rect.size.x();
83 position.y() = static_cast<float>(la.color_handles_rect.position.y());
84 }
85 };
86
87 struct opacity_point : public cgv::g2d::draggable {
88 static const float default_size;
89 vec2 val;
90
92 size = vec2(default_size);
93 position_is_center = true;
94 constraint_reference = CR_CENTER;
95 }
96
97 void update_val(const layout_attributes& la, const float scale_exponent) {
98 vec2 p = position - la.opacity_editor_rect.position;
99 val = p / la.opacity_editor_rect.size;
100
101 val = cgv::math::clamp(val, 0.0f, 1.0f);
102 val.y() = cgv::math::clamp(std::pow(val.y(), scale_exponent), 0.0f, 1.0f);
103 }
104
105 void update_pos(const layout_attributes& la, const float scale_exponent) {
106 val = cgv::math::clamp(val, 0.0f, 1.0f);
107
108 vec2 t = val;
109 t.y() = cgv::math::clamp(std::pow(t.y(), 1.0f / scale_exponent), 0.0f, 1.0f);
110
111 position = la.opacity_editor_rect.position + t * la.opacity_editor_rect.size;
112 }
113 };
114
115 bool mouse_is_on_overlay;
116 bool supports_opacity;
117 bool use_interpolation;
118 bool use_linear_filtering;
119 vec2 range;
120
121 ivec2 cursor_position;
122 std::string cursor_label;
123 bool show_value_label;
124 std::string value_label;
125 cgv::g2d::rect value_label_rectangle;
126
127 // general appearance
128 rgba handle_color = rgba(0.9f, 0.9f, 0.9f, 1.0f);
129 rgba highlight_color = rgba(0.5f, 0.5f, 0.5f, 1.0f);
130 std::string highlight_color_hex = "0x808080";
131 cgv::g2d::shape2d_style border_style, color_map_style, bg_style, hist_style, label_box_style, opacity_handle_style, polygon_style;
132 cgv::g2d::arrow2d_style color_handle_style;
133 cgv::g2d::line2d_style line_style;
134
135 // label appearance
136 cgv::g2d::text2d_style cursor_label_style, value_label_style;
137
138 std::vector<unsigned> histogram;
139 unsigned hist_max = 1;
140 unsigned hist_max_non_zero = 1;
141 bool hist_norm_ignore_zero = true;
142 float hist_norm_gamma = 1.0f;
143 cgv::type::DummyEnum histogram_type = (cgv::type::DummyEnum)2;
144
145 cgv::type::DummyEnum resolution;
146 float opacity_scale_exponent;
147
149 cgv::render::texture preview_tex;
150 cgv::render::texture hist_tex;
151
152 cgv::g2d::generic_2d_renderer color_handle_renderer, opacity_handle_renderer, line_renderer, polygon_renderer;
153 DEFINE_GENERIC_RENDER_DATA_CLASS(line_geometry, 2, vec2, position, vec2, texcoord);
154
156 cgv::render::color_map* cm = nullptr;
157 cgv::g2d::draggable_collection<color_point> color_points;
158 cgv::g2d::draggable_collection<opacity_point> opacity_points;
159
160 cgv::g2d::generic_render_data_vec2_rgba color_handles, opacity_handles;
161 line_geometry lines;
162 line_geometry triangles;
163
164 void reset() {
165 cm = nullptr;
166 color_points.clear();
167 opacity_points.clear();
168 color_handles.clear();
169 opacity_handles.clear();
170 lines.clear();
171 triangles.clear();
172 }
173
174 cgv::render::gl_color_map* get_gl_color_map() {
175 if(cm->has_texture_support())
176 return dynamic_cast<cgv::render::gl_color_map*>(cm);
177 return nullptr;
178 }
179 } cmc;
180
181 void init_styles() override;
182 void setup_preview_texture(cgv::render::context& ctx);
183 void init_preview_texture(cgv::render::context& ctx);
184
185 void add_point(const vec2& pos);
186 void remove_point(const cgv::g2d::draggable* ptr);
187 cgv::g2d::draggable* get_hit_point(const vec2& pos);
188
189 void update_value_label_rectangle(vec2 position, const cgv::g2d::rect& parent_rectangle);
190 void handle_color_drag(cgv::g2d::DragAction action);
191 void handle_opacity_drag(cgv::g2d::DragAction action);
192 //void handle_color_point_drag();
193 //void handle_opacity_point_drag();
194 void handle_drag_end();
195 std::string value_to_string(float value);
196 void sort_points();
197 void sort_color_points();
198 void sort_opacity_points();
199 void update_point_positions();
200 void update_color_map(bool is_data_change);
201 bool update_geometry();
202
203 std::function<void(void)> on_change_callback;
204 std::function<void(rgb)> on_color_point_select_callback;
205 std::function<void(void)> on_color_point_deselect_callback;
206
207 void create_gui_impl() override;
208
209public:
211 std::string get_type_name() const override { return "color_map_editor"; }
212
213 void clear(cgv::render::context& ctx) override;
214
215 bool handle_key_event(cgv::gui::key_event& e) override;
216 bool handle_mouse_event(cgv::gui::mouse_event& e, cgv::ivec2 local_mouse_pos) override;
217 void handle_member_change(const cgv::utils::pointer_test& m) override;
218
219 bool init(cgv::render::context& ctx) override;
220 void init_frame(cgv::render::context& ctx) override;
221 void draw_content(cgv::render::context& ctx) override;
222
223 void handle_theme_change(const cgv::gui::theme_info& theme) override;
224
225 bool get_opacity_support() { return supports_opacity; }
226 void set_opacity_support(bool flag);
227
228 vec2 get_range() const { return range; }
229 void set_range(vec2 r) { range = r; }
230
231 cgv::render::color_map* get_color_map() { return cmc.cm; }
232 void set_color_map(cgv::render::color_map* cm);
233
234 void set_histogram_data(const std::vector<unsigned> data);
235
236 void set_selected_color(rgb color);
237
238 void set_on_change_callback(std::function<void(void)> cb) { on_change_callback = cb; }
239 void set_on_color_point_select_callback(std::function<void(rgb)> cb) { on_color_point_select_callback = cb; }
240 void set_on_color_point_deselect_callback(std::function<void(void)> cb) { on_color_point_deselect_callback = cb; }
241};
242
243typedef cgv::data::ref_ptr<color_map_editor> color_map_editor_ptr;
244
245static void connect_color_selector_to_color_map_editor(const color_map_editor_ptr cme_ptr, const color_selector_ptr cs_ptr) {
246 if(cme_ptr && cs_ptr) {
247 cme_ptr->set_on_color_point_select_callback(std::bind(&cgv::app::color_selector::set_rgb_color, cs_ptr, std::placeholders::_1));
248 cme_ptr->set_on_color_point_deselect_callback(std::bind(&cgv::app::color_selector::set_visibility, cs_ptr, false));
249 cs_ptr->set_on_change_rgb_callback(std::bind(&cgv::app::color_map_editor::set_selected_color, cme_ptr, std::placeholders::_1));
250 }
251}
252
253}
254}
255
256#include <cgv/config/lib_end.h>
std::string get_type_name() const override
overload to return the type name of this object. By default the type interface is queried over get_ty...
void set_visibility(bool visible)
set the visibility of the overlay
Definition overlay.cxx:113
reference counted pointer, which can work together with types that are derived from ref_counted,...
Definition ref_ptr.h:160
class to represent all possible keyboard events with the EID_KEY
Definition key_event.h:23
class to represent all possible mouse events with the EID_MOUSE
Definition mouse_event.h:33
T & y()
second element
Definition fvec.h:159
T & x()
first element
Definition fvec.h:155
base class for all drawables, which is independent of the used rendering API.
Definition context.h:621
the texture class encapsulates all functionality independent of the rendering api.
Definition texture.h:15
DummyEnum
some enum to mark an integral parameter to be of enum type
the cgv namespace
Definition print.h:11