Tones Node port from MateriaMaker (Part 2).

This commit is contained in:
Relintai 2023-03-03 18:02:06 +01:00
parent c232aa4154
commit 51b63cae71
4 changed files with 385 additions and 1 deletions

View File

@ -11,6 +11,8 @@
#include "../../../algos/mm_algos.h"
#include "tones_editor_cursor.h"
void MMTonesEditor::set_value(const Ref<MMTones> &v) {
if (_node == v) {
return;
@ -29,6 +31,123 @@ void MMTonesEditor::set_value(const Ref<MMTones> &v) {
on_input_property_changed();
}
enum ParameterTypes {
PARAMETER_TYPE_IN_MIN = 0,
PARAMETER_TYPE_IN_MID,
PARAMETER_TYPE_IN_MAX,
PARAMETER_TYPE_OUT_MIN,
PARAMETER_TYPE_OUT_MAX,
};
Color MMTonesEditor::get_parameter(ParameterTypes type) {
if (!_node.is_valid()) {
return Color();
}
switch (type) {
case PARAMETER_TYPE_IN_MIN:
return _node->get_in_min();
break;
case PARAMETER_TYPE_IN_MID:
return _node->get_in_mid();
break;
case PARAMETER_TYPE_IN_MAX:
return _node->get_in_max();
break;
case PARAMETER_TYPE_OUT_MIN:
return _node->get_out_min();
break;
case PARAMETER_TYPE_OUT_MAX:
return _node->get_out_max();
break;
default:
break;
}
return Color();
}
float MMTonesEditor::get_parameter_current_mode(ParameterTypes type) {
Color color = get_parameter(type);
switch (_current_mode) {
case MODE_LUMINANCE:
return (color.r + color.g + color.b) / 3.0;
break;
case MODE_RED:
return color.r;
break;
case MODE_GREEN:
return color.g;
break;
case MODE_BLUE:
return color.b;
break;
case MODE_ALPHA:
return color.a;
break;
}
return 0;
}
void MMTonesEditor::set_parameter(ParameterTypes type, const Color &val) {
if (!_node.is_valid()) {
return;
}
switch (type) {
case PARAMETER_TYPE_IN_MIN:
_node->set_in_min(val);
break;
case PARAMETER_TYPE_IN_MID:
_node->set_in_mid(val);
break;
case PARAMETER_TYPE_IN_MAX:
_node->set_in_max(val);
break;
case PARAMETER_TYPE_OUT_MIN:
_node->set_out_min(val);
break;
case PARAMETER_TYPE_OUT_MAX:
_node->set_out_max(val);
break;
default:
break;
}
}
void MMTonesEditor::set_parameter_current_mode(ParameterTypes type, float val, float d) {
if (!_node.is_valid()) {
return;
}
Color color = get_parameter(type);
switch (_current_mode) {
case MODE_LUMINANCE:
color.r = val;
color.g = val;
color.b = val;
color.a = d;
break;
case MODE_RED:
color.r = val;
break;
case MODE_GREEN:
color.g = val;
break;
case MODE_BLUE:
color.b = val;
break;
case MODE_ALPHA:
color.a = val;
break;
}
set_parameter(type, color);
}
Ref<ImageTexture> MMTonesEditor::make_histogram(const Ref<Image> &img) {
ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>());
@ -66,9 +185,11 @@ MMTonesEditor::MMTonesEditor() {
_mode_ob->add_item("Alpha", MODE_ALPHA);
_mode_ob->select(MODE_LUMINANCE);
_mode_ob->connect("item_selected", this, "on_mode_item_selected");
Button *auto_button = memnew(Button);
bar->add_child(auto_button);
auto_button->connect("pressed", this, "on_auto_levels_pressed");
auto_button->set_text("AL");
auto_button->set_tooltip("Set levels automatically");
@ -83,9 +204,35 @@ MMTonesEditor::MMTonesEditor() {
_histogram_tr->set_h_size_flags(Control::SIZE_EXPAND_FILL);
add_child(_histogram_tr);
_cursor_in_min = memnew(MMTonesEditorCursor);
_cursor_in_mid = memnew(MMTonesEditorCursor);
_cursor_in_max = memnew(MMTonesEditorCursor);
_cursor_out_min = memnew(MMTonesEditorCursor);
_cursor_out_max = memnew(MMTonesEditorCursor);
_cursor_in_min->initialize(Color(0, 0, 0), 0, true);
_cursor_in_mid->initialize(Color(0.5, 0.5, 0.5), 0.5, true);
_cursor_in_max->initialize(Color(1, 1, 1), 1, true);
_cursor_out_min->initialize(Color(0, 0, 0), 0, false);
_cursor_out_max->initialize(Color(1, 1, 1), 1, false);
_histogram_tr->add_child(_cursor_in_min);
_histogram_tr->add_child(_cursor_in_mid);
_histogram_tr->add_child(_cursor_in_max);
_histogram_tr->add_child(_cursor_out_min);
_histogram_tr->add_child(_cursor_out_max);
_cursor_in_min->connect("cursor_value_changed", this, "on_cursor_value_changed");
_cursor_in_mid->connect("cursor_value_changed", this, "on_cursor_value_changed");
_cursor_in_max->connect("cursor_value_changed", this, "on_cursor_value_changed");
_cursor_out_min->connect("cursor_value_changed", this, "on_cursor_value_changed");
_cursor_out_max->connect("cursor_value_changed", this, "on_cursor_value_changed");
spacer = memnew(Control);
spacer->set_custom_minimum_size(Vector2(0, 4));
add_child(spacer);
on_mode_item_selected(MODE_LUMINANCE);
}
MMTonesEditor::~MMTonesEditor() {
@ -107,6 +254,85 @@ void MMTonesEditor::on_input_property_changed() {
_histogram_tr->set_texture(make_histogram(img));
}
void MMTonesEditor::on_auto_levels_pressed() {
// TODO needs proper histogram generation
/*
var histogram = $Histogram.get_histogram_texture().get_data()
histogram.lock()
var in_min : int = -1
var in_mid : int = -1
var in_mid_value : float = 0
var in_max : int = -1
var histogram_size = histogram.get_size().x
for i in range(histogram_size):
var color : Color = histogram.get_pixel(i, 0)
var value : float
match $Bar/Mode.selected:
0:
value = (color.r+color.g+color.b)/3.0
1:
value = color.r
2:
value = color.g
3:
value = color.b
4:
value = color.a
if value > 0.0:
if in_min == -1:
in_min = i
in_max = i
if in_mid_value < value:
in_mid = i
in_mid_value = value
histogram.unlock()
cursor_in_min.update_value(in_min/(histogram_size-1))
cursor_in_mid.update_value(in_mid/(histogram_size-1))
cursor_in_max.update_value(in_max/(histogram_size-1))
*/
}
void MMTonesEditor::on_mode_item_selected(int id) {
_current_mode = static_cast<Modes>(id);
_cursor_in_min->set_value(get_parameter_current_mode(PARAMETER_TYPE_IN_MIN));
_cursor_in_mid->set_value(get_parameter_current_mode(PARAMETER_TYPE_IN_MID));
_cursor_in_max->set_value(get_parameter_current_mode(PARAMETER_TYPE_IN_MAX));
_cursor_out_min->set_value(get_parameter_current_mode(PARAMETER_TYPE_OUT_MIN));
_cursor_out_max->set_value(get_parameter_current_mode(PARAMETER_TYPE_OUT_MAX));
}
void MMTonesEditor::on_cursor_value_changed(Control *cursor, float position) {
if (cursor == _cursor_in_min) {
set_parameter_current_mode(PARAMETER_TYPE_IN_MIN, position, 0);
} else if (cursor == _cursor_in_mid) {
set_parameter_current_mode(PARAMETER_TYPE_IN_MID, position, 0.5);
} else if (cursor == _cursor_in_max) {
set_parameter_current_mode(PARAMETER_TYPE_IN_MAX, position, 1);
} else if (cursor == _cursor_out_min) {
set_parameter_current_mode(PARAMETER_TYPE_OUT_MIN, position, 0);
} else if (cursor == _cursor_out_max) {
set_parameter_current_mode(PARAMETER_TYPE_OUT_MAX, position, 1);
}
}
void MMTonesEditor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_RESIZED: {
_cursor_in_min->resize();
_cursor_in_mid->resize();
_cursor_in_max->resize();
_cursor_out_min->resize();
_cursor_out_max->resize();
} break;
default:
break;
}
}
void MMTonesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("on_input_property_changed"), &MMTonesEditor::on_input_property_changed);
ClassDB::bind_method(D_METHOD("on_auto_levels_pressed"), &MMTonesEditor::on_auto_levels_pressed);
ClassDB::bind_method(D_METHOD("on_mode_item_selected"), &MMTonesEditor::on_mode_item_selected);
ClassDB::bind_method(D_METHOD("on_cursor_value_changed"), &MMTonesEditor::on_cursor_value_changed);
}

View File

@ -9,6 +9,7 @@ class MMTones;
class OptionButton;
class TextureRect;
class ImageTexture;
class MMTonesEditorCursor;
class MMTonesEditor : public VBoxContainer {
GDCLASS(MMTonesEditor, VBoxContainer);
@ -28,6 +29,20 @@ public:
void set_value(const Ref<MMTones> &v);
enum ParameterTypes {
PARAMETER_TYPE_IN_MIN = 0,
PARAMETER_TYPE_IN_MID,
PARAMETER_TYPE_IN_MAX,
PARAMETER_TYPE_OUT_MIN,
PARAMETER_TYPE_OUT_MAX,
};
Color get_parameter(ParameterTypes type);
float get_parameter_current_mode(ParameterTypes type);
void set_parameter(ParameterTypes type, const Color &val);
void set_parameter_current_mode(ParameterTypes type, float val, float d);
Ref<ImageTexture> make_histogram(const Ref<Image> &img);
Ref<ImageTexture> make_default_histogram();
@ -36,13 +51,26 @@ public:
protected:
void on_input_property_changed();
void on_auto_levels_pressed();
void on_mode_item_selected(int id);
void on_cursor_value_changed(Control *cursor, float position);
void _notification(int p_what);
static void _bind_methods();
Ref<MMTones> _node;
Modes _current_mode;
OptionButton *_mode_ob;
TextureRect *_histogram_tr;
MMTonesEditorCursor *_cursor_in_min;
MMTonesEditorCursor *_cursor_in_mid;
MMTonesEditorCursor *_cursor_in_max;
MMTonesEditorCursor *_cursor_out_min;
MMTonesEditorCursor *_cursor_out_max;
};
#endif

View File

@ -1,11 +1,122 @@
#include "tones_editor_cursor.h"
void MMTonesEditorCursor::set_value(float val) {
_position = val;
Control *parent = get_parent_control();
if (!parent) {
return;
}
Vector2 pos = get_position();
set_position(Vector2(_position * parent->get_size().x - 0.5 * CURSOR_WIDTH, pos.y));
}
void MMTonesEditorCursor::update_value(float val) {
if (!Math::is_equal_approx(val, _position)) {
set_value(val);
emit_signal("cursor_value_changed", this, _position);
update();
}
}
void MMTonesEditorCursor::initialize(const Color &color, float position, bool top) {
_color = color;
_position = position;
_top = top;
}
void MMTonesEditorCursor::resize() {
Control *parent = get_parent_control();
if (!parent) {
return;
}
Vector2 position = get_position();
if (_top) {
set_position(Vector2(position.x, -2));
} else {
set_position(Vector2(position.x, parent->get_size().y + 2 - CURSOR_HEIGHT));
}
set_size(Vector2(CURSOR_WIDTH, CURSOR_HEIGHT));
set_value(_position);
}
void MMTonesEditorCursor::_gui_input(const Ref<InputEvent> &p_event) {
Ref<InputEventMouseMotion> iemm = p_event;
if (iemm.is_valid()) {
if (((iemm->get_button_mask() & 1) != 0)) {
Control *parent = get_parent_control();
if (!parent) {
return;
}
Vector2 parent_size = parent->get_size();
Vector2 pos = get_position();
pos.x += iemm->get_relative().x;
pos.x = MIN(MAX(-0.5 * CURSOR_WIDTH, pos.x), parent_size.x - 0.5 * CURSOR_WIDTH);
update_value((pos.x + 0.5 * CURSOR_WIDTH) / parent_size.x);
}
}
}
MMTonesEditorCursor::MMTonesEditorCursor() {
}
MMTonesEditorCursor::~MMTonesEditorCursor() {
}
void MMTonesEditorCursor::_bind_methods() {
void MMTonesEditorCursor::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
Vector<Point2> polygon;
polygon.resize(4);
if (_top) {
polygon.write[0] = Vector2(0, 0);
polygon.write[1] = Vector2(CURSOR_WIDTH / 2.0, CURSOR_HEIGHT);
polygon.write[2] = Vector2(CURSOR_WIDTH, 0);
polygon.write[3] = Vector2(0, 0);
} else {
polygon.write[0] = Vector2(0, CURSOR_HEIGHT);
polygon.write[1] = Vector2(CURSOR_WIDTH / 2.0, 0);
polygon.write[2] = Vector2(CURSOR_WIDTH, CURSOR_HEIGHT);
polygon.write[3] = Vector2(0, CURSOR_HEIGHT);
}
Color c = _color;
c.a = 1.0;
draw_colored_polygon(polygon, c);
float outline_color = 0;
if (_position < 0.5) {
outline_color = 1.0;
}
draw_polyline(polygon, Color(outline_color, outline_color, outline_color), 1.0, true);
} break;
case NOTIFICATION_RESIZED:
case NOTIFICATION_READY: {
resize();
} break;
default:
break;
}
}
void MMTonesEditorCursor::_bind_methods() {
ADD_SIGNAL(MethodInfo("cursor_value_changed", PropertyInfo(Variant::OBJECT, "cursor", PROPERTY_HINT_RESOURCE_TYPE, "Control"), PropertyInfo(Variant::REAL, "position")));
ClassDB::bind_method(D_METHOD("_gui_input"), &MMTonesEditorCursor::_gui_input);
}

View File

@ -7,11 +7,30 @@ class MMTonesEditorCursor : public TextureRect {
GDCLASS(MMTonesEditorCursor, TextureRect);
public:
enum {
CURSOR_WIDTH = 12,
CURSOR_HEIGHT = 12,
};
void set_value(float val);
void update_value(float val);
void initialize(const Color &color, float position, bool top);
void resize();
void _gui_input(const Ref<InputEvent> &p_event);
MMTonesEditorCursor();
~MMTonesEditorCursor();
protected:
void _notification(int p_what);
static void _bind_methods();
Color _color;
float _position;
bool _top;
};
#endif