Tones Node port from MaterialMaker (Part 1).

This commit is contained in:
Relintai 2023-03-03 15:29:03 +01:00
parent 0f02468984
commit 6876c87050
15 changed files with 697 additions and 9 deletions

View File

@ -50,6 +50,9 @@ sources = [
"editor/widgets/polygon_edit/polygon_editor.cpp",
"editor/widgets/polygon_edit/polygon_view.cpp",
"editor/widgets/tones_editor/tones_editor.cpp",
"editor/widgets/tones_editor/tones_editor_cursor.cpp",
"nodes/uniform/uniform.cpp",
"nodes/uniform/greyscale_uniform.cpp",
@ -163,6 +166,7 @@ sources = [
"nodes/filter/adjust_hsv.cpp",
"nodes/filter/tones_step.cpp",
"nodes/filter/tones_map.cpp",
"nodes/filter/tones.cpp",
]
if env["tools"]:

View File

@ -2,6 +2,7 @@
#include "mm_algos.h"
#include "core/math/math_funcs.h"
#include "core/math/vector4.h"
//pattern.mmg;
//----------------------;
@ -258,6 +259,26 @@ Vector2 MMAlgos::stepv2(const Vector2 &edge, const Vector2 &x) {
return ret;
}
Color MMAlgos::stepc(const Color &edge, const Color &x) {
Color ret;
ret.r = step(edge.r, x.r);
ret.g = step(edge.g, x.g);
ret.b = step(edge.b, x.b);
ret.a = step(edge.a, x.a);
return ret;
}
Color MMAlgos::mixc(const Color &a, const Color &b, const Color &t) {
Color ret;
ret.r = Math::lerp(a.r, b.r, t.r);
ret.g = Math::lerp(a.g, b.g, t.g);
ret.b = Math::lerp(a.b, b.b, t.b);
ret.a = Math::lerp(a.a, b.a, t.a);
return ret;
}
Vector2 MMAlgos::signv2(const Vector2 &x) {
Vector2 ret;
ret.x = SGN(x.x);
@ -796,6 +817,23 @@ Color MMAlgos::adjust_hsv(const Color &color, const float hue, const float satur
return Color(h.x, h.y, h.z, color.a);
}
//tones.mmg;
//vec4 adjust_levels(vec4 input, vec4 in_min, vec4 in_mid, vec4 in_max, vec4 out_min, vec4 out_max) {
// input = clamp((input-in_min)/(in_max-in_min), 0.0, 1.0);
// in_mid = (in_mid-in_min)/(in_max-in_min);
// vec4 dark = step(in_mid, input);
// input = 0.5*mix(input/(in_mid), 1.0+(input-in_mid)/(1.0-in_mid), dark);
// return out_min+input*(out_max-out_min);
//}
Color MMAlgos::adjust_levels(const Color &p_input, const Color &p_in_min, const Color &p_in_mid, const Color &p_in_max, const Color &p_out_min, const Color &p_out_max) {
Color input = (p_input - p_in_min) / (p_in_max - p_in_min).clamp();
Color in_mid = (p_in_mid - p_in_min) / (p_in_max - p_in_min);
Color dark = stepc(in_mid, p_input);
input = Color(0.5, 0.5, 0.5, 0.5) * mixc(input / (in_mid), Color(1, 1, 1, 1) + (input - in_mid) / (Color(1, 1, 1, 1) - in_mid), dark);
return p_out_min + input * (p_out_max - p_out_min);
}
//brightness, min: -1, max: 1, step: 0.01, default: 0;
//contrast, min: -1, max: 1, step: 0.01, default: 1;
//input: default: vec4(0.5 ,0.5, 0.5, 1.0) -> img;
@ -1011,14 +1049,6 @@ Vector3 MMAlgos::blend_difference(const Vector2 &uv, const Vector3 &c1, const Ve
return opacity * clampv3(c2 - c1, Vector3(), Vector3(1, 1, 1)) + (1.0 - opacity) * c2;
}
//vec4 adjust_levels(vec4 input, vec4 in_min, vec4 in_mid, vec4 in_max, vec4 out_min, vec4 out_max) {\n\t;
// input = CLAMP((input-in_min)/(in_max-in_min), 0.0, 1.0);\n\t;
// in_mid = (in_mid-in_min)/(in_max-in_min);\n\t;
// vec4 dark = step(in_mid, input);\n\t;
//;
// input = 0.5*mix(input/(in_mid), 1.0+(input-in_mid)/(1.0-in_mid), dark);\n\t;
// return out_min+input*(out_max-out_min);\n;
//};
// === GRADIENTS.GD =====;
//note: data : PoolRealArray -> pos, r, g, b, a, pos, r, g, b, a ....;
//gradient.mmg;
@ -5596,6 +5626,215 @@ Vector2 MMAlgos::custom_uv_transform(const Vector2 &uuv, const Vector2 &cst_scal
return uv;
}
Ref<Image> MMAlgos::generate_histogram(const Ref<Image> &input, const int texture_size) {
ERR_FAIL_COND_V(!input.is_valid(), Ref<Image>());
Ref<Image> scaled_input;
scaled_input.instance();
scaled_input->copy_internals_from(input);
scaled_input->resize(texture_size, texture_size);
Ref<Image> step_1;
step_1.instance();
step_1->copy_internals_from(scaled_input);
scaled_input->lock();
step_1->lock();
// texture_size, texture_size
//step 1
/*
shader_type canvas_item;
render_mode blend_disabled;
uniform sampler2D tex;
uniform float size = 256;
void fragment() {
float e = 1.0 / size;
vec4 sum = vec4(0.0);
for (float y = 0.5 * e; y < 1.0; y += e) {
sum += max(vec4(0.0), vec4(1.0) - 16.0 * abs(texture(tex, vec2(UV.x, y)) - UV.y));
}
COLOR = sum / size;
}
*/
Vector2i size = step_1->get_size();
for (int x = 0; x < size.x; ++x) {
for (int y = 0; y < size.y; ++y) {
float e = 1.0 / size.y;
Color sum = Color();
for (float yy = 0.5 * e; yy < 1.0; yy += e) {
Color sic = scaled_input->get_pixel(x, yy * size.y);
sic -= Color(e, e, e, e);
sic.r = MAX(0, 1.0 - 16.0 * ABS(sic.r));
sic.g = MAX(0, 1.0 - 16.0 * ABS(sic.g));
sic.b = MAX(0, 1.0 - 16.0 * ABS(sic.b));
sic.a = MAX(0, 1.0 - 16.0 * ABS(sic.a));
sum += sic;
}
sum.r /= size.y;
sum.g /= size.y;
sum.b /= size.y;
sum.a /= size.y;
step_1->set_pixel(x, y, sum);
}
}
step_1->unlock();
scaled_input->unlock();
//texture_size, 2
//step 2
/*
shader_type canvas_item;
render_mode blend_disabled;
uniform sampler2D tex;
uniform float size = 256;
void fragment() {
float e = 1.0 / size;
vec4 sum = vec4(0.0);
for (float y = 0.5 * e; y < 1.0; y += e) {
sum += texture(tex, vec2(y, UV.x));
}
COLOR = sum / size;
}
*/
Ref<Image> step_2;
step_2.instance();
step_2->copy_internals_from(step_1);
step_2->resize(texture_size, 2);
scaled_input->lock();
step_2->lock();
size = step_2->get_size();
for (int x = 0; x < size.x; ++x) {
for (int y = 0; y < size.y; ++y) {
float e = 1.0 / size.y;
Color sum = Color();
for (float yy = 0.5 * e; yy < 1.0; yy += e) {
Color sic = scaled_input->get_pixel(yy * size.y, x);
sum += sic;
}
sum.r /= size.y;
sum.g /= size.y;
sum.b /= size.y;
sum.a /= size.y;
step_2->set_pixel(x, y, sum);
}
}
step_2->unlock();
scaled_input->unlock();
//step 3
//texture_size, texture_size
/*
shader_type canvas_item;
render_mode blend_disabled;
uniform sampler2D tex;
uniform float gradient_width = 0.1;
void fragment() {
if (abs(fract(UV.y + gradient_width)) < 2.0 * gradient_width) {
COLOR = vec4(vec3(UV.x), 1.0);
} else {
float e = 1.0 / 256.0;
vec4 highest = vec4(0.0);
for (float x = 0.5 * e; x < 1.0; x += e) {
highest = max(highest, texture(tex, vec2(x, 0.0)));
}
vec4 raw_value = texture(tex, vec2(UV.x, 0.0));
vec4 value = step(vec4(1.0 - gradient_width - UV.y) * highest / (1.0 - 2.0 * gradient_width), raw_value);
float alpha = step(2.0 * gradient_width, dot(value, vec4(1.0)));
COLOR = vec4(mix(value.rgb, vec3(0.5), 0.3 * value.a), alpha);
}
}
*/
Ref<Image> result;
result.instance();
result->copy_internals_from(input);
result->resize(texture_size, texture_size);
result->lock();
step_2->lock();
size = result->get_size();
float gradient_width = 0.1;
for (int x = 0; x < size.x; ++x) {
float uv_1_x = (1.0 / size.x);
float uv_x = uv_1_x * x;
for (int y = 0; y < size.y; ++y) {
float e = 1.0 / size.y;
float uv_y = e * y;
if (ABS(MMAlgos::fractf(uv_y + gradient_width)) < 2.0 * gradient_width) {
result->set_pixel(x, y, Color(uv_x, uv_x, uv_x, 1));
} else {
Color highest = Color(0, 0, 0, 0);
for (float xx = 0.5 * uv_1_x; xx < 1.0; xx += uv_1_x) {
Color sic = step_2->get_pixel(xx * uv_1_x, 0);
highest.r = MAX(highest.r, sic.r);
highest.g = MAX(highest.g, sic.g);
highest.b = MAX(highest.b, sic.b);
highest.a = MAX(highest.a, sic.a);
}
Color raw_value = step_2->get_pixel(x * uv_1_x, 0);
Vector4 highest_v4 = Vector4(highest.r, highest.g, highest.b, highest.a);
float gv = 1.0 - gradient_width - uv_y;
Vector4 value = Vector4(gv, gv, gv, gv) * highest_v4 / (1.0 - 2.0 * gradient_width);
value.x = step(value.x, raw_value.r);
value.y = step(value.y, raw_value.g);
value.z = step(value.z, raw_value.b);
value.w = step(value.w, raw_value.a);
float alpha = step(2.0 * gradient_width, value.dot(Vector4(1, 1, 1, 1)));
Vector3 val3 = Vector3(value.x, value.y, value.z);
val3 = val3.linear_interpolate(Vector3(0.5, 0.5, 0.5), 0.3 * value.w);
Color f = Color(val3.x, val3.y, val3.z, alpha);
result->set_pixel(x, y, f);
}
}
}
step_2->unlock();
result->unlock();
return result;
}
void MMAlgos::register_node_class(const String &category, const String &cls) {
for (int i = 0; i < mm_node_registry.size(); ++i) {
const MMNodeRegistryCategory &categ = mm_node_registry[i];

View File

@ -6,6 +6,7 @@
#include "core/math/vector3.h"
#include "core/containers/pool_vector.h"
#include "core/variant/variant.h"
#include "core/io/image.h"
#include "core/object/reference.h"
@ -39,6 +40,8 @@ public:
static Vector3 rand3(const Vector2 &x);
static float step(const float edge, const float x);
static Vector2 stepv2(const Vector2 &edge, const Vector2 &x);
static Color stepc(const Color &edge, const Color &x);
static Color mixc(const Color &a, const Color &b, const Color &t);
static Vector2 signv2(const Vector2 &x);
static Vector2 transform(const Vector2 &uv, const Vector2 &translate, const float rotate, const Vector2 &scale, const bool repeat);
static float fractf(const float x);
@ -63,6 +66,7 @@ public:
static Vector3 rgb_to_hsv(const Vector3 &c);
static Vector3 hsv_to_rgb(const Vector3 &c);
static Color adjust_hsv(const Color &color, const float hue, const float saturation, const float value);
static Color adjust_levels(const Color &color, const Color &in_min, const Color &in_mid, const Color &in_max, const Color &out_min, const Color &out_max);
static Color brightness_contrast(const Color &color, const float brightness, const float contrast);
static float grayscale_min(const Vector3 &c);
static float grayscale_max(const Vector3 &c);
@ -285,6 +289,8 @@ public:
static Vector2 get_from_tileset(const float count, const float pseed, const Vector2 &uv);
static Vector2 custom_uv_transform(const Vector2 &uv, const Vector2 &cst_scale, const float rnd_rotate, const float rnd_scale, const Vector2 &pseed);
static Ref<Image> generate_histogram(const Ref<Image> &input, const int texture_size = 256);
static void register_node_class(const String &category, const String &cls);
static void unregister_node_class(const String &category, const String &cls);

View File

@ -108,6 +108,13 @@ Vector2 _MMAlgos::stepv2(const Vector2 &edge, const Vector2 &x) {
return MMAlgos::stepv2(edge, x);
}
Color _MMAlgos::stepc(const Color &edge, const Color &x) {
return MMAlgos::stepc(edge, x);
}
Color _MMAlgos::mixc(const Color &a, const Color &b, const Color &t) {
return MMAlgos::mixc(a, b, t);
}
Vector2 _MMAlgos::signv2(const Vector2 &x) {
return MMAlgos::signv2(x);
}
@ -204,6 +211,10 @@ Color _MMAlgos::adjust_hsv(const Color &color, const float hue, const float satu
return MMAlgos::adjust_hsv(color, hue, saturation, value);
}
Color _MMAlgos::adjust_levels(const Color &color, const Color &in_min, const Color &in_mid, const Color &in_max, const Color &out_min, const Color &out_max) {
return MMAlgos::adjust_levels(color, in_min, in_mid, in_max, out_min, out_max);
}
Color _MMAlgos::brightness_contrast(const Color &color, const float brightness, const float contrast) {
return MMAlgos::brightness_contrast(color, brightness, contrast);
}
@ -1012,6 +1023,10 @@ Vector2 _MMAlgos::custom_uv_transform(const Vector2 &uv, const Vector2 &cst_scal
return MMAlgos::custom_uv_transform(uv, cst_scale, rnd_rotate, rnd_scale, pseed);
}
Ref<Image> _MMAlgos::generate_histogram(const Ref<Image> &input, const int texture_size) {
return MMAlgos::generate_histogram(input, texture_size);
}
void _MMAlgos::register_node_class(const String &category, const String &cls) {
MMAlgos::register_node_class(category, cls);
}
@ -1065,6 +1080,8 @@ void _MMAlgos::_bind_methods() {
ClassDB::bind_method(D_METHOD("rand3", "x"), &_MMAlgos::rand3);
ClassDB::bind_method(D_METHOD("step", "edge", "x"), &_MMAlgos::step);
ClassDB::bind_method(D_METHOD("stepv2", "edge", "x"), &_MMAlgos::stepv2);
ClassDB::bind_method(D_METHOD("stepc", "edge", "x"), &_MMAlgos::stepc);
ClassDB::bind_method(D_METHOD("mixc", "a", "b", "c"), &_MMAlgos::mixc);
ClassDB::bind_method(D_METHOD("signv2", "x"), &_MMAlgos::signv2);
ClassDB::bind_method(D_METHOD("transform", "uv", "translate", "rotate", "scale", "repeat"), &_MMAlgos::transform);
ClassDB::bind_method(D_METHOD("fractf", "x"), &_MMAlgos::fractf);
@ -1089,6 +1106,7 @@ void _MMAlgos::_bind_methods() {
ClassDB::bind_method(D_METHOD("rgb_to_hsv", "c"), &_MMAlgos::rgb_to_hsv);
ClassDB::bind_method(D_METHOD("hsv_to_rgb", "c"), &_MMAlgos::hsv_to_rgb);
ClassDB::bind_method(D_METHOD("adjust_hsv", "color", "hue", "saturation", "value"), &_MMAlgos::adjust_hsv);
ClassDB::bind_method(D_METHOD("adjust_levels", "color", "in_min", "in_mid", "in_max", "out_min", "out_max"), &_MMAlgos::adjust_levels);
ClassDB::bind_method(D_METHOD("brightness_contrast", "color", "brightness", "contrast"), &_MMAlgos::brightness_contrast);
ClassDB::bind_method(D_METHOD("grayscale_min", "c"), &_MMAlgos::grayscale_min);
ClassDB::bind_method(D_METHOD("grayscale_max", "c"), &_MMAlgos::grayscale_max);
@ -1292,6 +1310,8 @@ void _MMAlgos::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_from_tileset", "count", "pseed", "uv"), &_MMAlgos::get_from_tileset);
ClassDB::bind_method(D_METHOD("custom_uv_transform", "uv", "cst_scale", "rnd_rotate", "rnd_scale", "pseed"), &_MMAlgos::custom_uv_transform);
ClassDB::bind_method(D_METHOD("generate_histogram", "input", "texture_size"), &_MMAlgos::generate_histogram, 256);
ClassDB::bind_method(D_METHOD("register_node_class", "category", "cls"), &_MMAlgos::register_node_class);
ClassDB::bind_method(D_METHOD("unregister_node_class", "category", "cls"), &_MMAlgos::unregister_node_class);

View File

@ -1,10 +1,11 @@
#ifndef MM_ALGOS_BIND_H
#define MM_ALGOS_BIND_H
#include "core/containers/pool_vector.h"
#include "core/io/image.h"
#include "core/math/color.h"
#include "core/math/vector2.h"
#include "core/math/vector3.h"
#include "core/containers/pool_vector.h"
#include "core/variant/variant.h"
#include "core/object/object.h"
@ -39,6 +40,8 @@ public:
Vector3 rand3(const Vector2 &x);
float step(const float edge, const float x);
Vector2 stepv2(const Vector2 &edge, const Vector2 &x);
Color stepc(const Color &edge, const Color &x);
Color mixc(const Color &a, const Color &b, const Color &t);
Vector2 signv2(const Vector2 &x);
Vector2 transform(const Vector2 &uv, const Vector2 &translate, const float rotate, const Vector2 &scale, const bool repeat);
float fractf(const float x);
@ -63,6 +66,7 @@ public:
Vector3 rgb_to_hsv(const Vector3 &c);
Vector3 hsv_to_rgb(const Vector3 &c);
Color adjust_hsv(const Color &color, const float hue, const float saturation, const float value);
Color adjust_levels(const Color &color, const Color &in_min, const Color &in_mid, const Color &in_max, const Color &out_min, const Color &out_max);
Color brightness_contrast(const Color &color, const float brightness, const float contrast);
float grayscale_min(const Vector3 &c);
float grayscale_max(const Vector3 &c);
@ -266,6 +270,8 @@ public:
Vector2 get_from_tileset(const float count, const float pseed, const Vector2 &uv);
Vector2 custom_uv_transform(const Vector2 &uv, const Vector2 &cst_scale, const float rnd_rotate, const float rnd_scale, const Vector2 &pseed);
Ref<Image> generate_histogram(const Ref<Image> &input, const int texture_size = 256);
void register_node_class(const String &category, const String &cls);
void unregister_node_class(const String &category, const String &cls);

View File

@ -134,6 +134,7 @@ def get_doc_classes():
"MMAdjustHsv",
"MMTonesStep",
"MMTonesMap",
"MMTones",
]
def get_doc_path():

View File

@ -22,6 +22,9 @@
#include "widgets/gradient_editor/gradient_editor.h"
#include "widgets/image_picker_button/image_picker_button.h"
#include "widgets/polygon_edit/polygon_edit.h"
#include "widgets/tones_editor/tones_editor.h"
#include "../nodes/filter/tones.h"
Ref<PackedScene> MMGraphNode::get_gradient_editor_scene() {
return gradient_editor_scene;
@ -187,6 +190,17 @@ int MMGraphNode::add_slot_curve() {
return slot_idx;
}
int MMGraphNode::add_slot_tones() {
ERR_FAIL_COND_V(!_node->is_class("MMTones"), 0);
MMTonesEditor *te = memnew(MMTonesEditor);
int slot_idx = add_slot(MMNodeUniversalProperty::SLOT_TYPE_NONE, MMNodeUniversalProperty::SLOT_TYPE_NONE, "", "", te);
te->set_value(_node);
//ge.texture = _node.call(getter, _material, slot_idx);
//properties[slot_idx].append(ge.texture);
return slot_idx;
}
int MMGraphNode::add_slot_color(const String &getter, const String &setter) {
ColorPickerButton *cp = memnew(ColorPickerButton);
int slot_idx = add_slot(MMNodeUniversalProperty::SLOT_TYPE_NONE, MMNodeUniversalProperty::SLOT_TYPE_NONE, getter, setter, cp);

View File

@ -53,6 +53,7 @@ public:
int add_slot_gradient();
int add_slot_polygon();
int add_slot_curve();
int add_slot_tones();
int add_slot_color(const String &getter, const String &setter);
int add_slot_color_universal(const Ref<MMNodeUniversalProperty> &property);
int add_slot_label(const String &getter, const String &setter, const String &slot_name);

View File

@ -0,0 +1,116 @@
#include "tones_editor.h"
#include "scene/resources/texture.h"
#include "../../../nodes/filter/tones.h"
#include "scene/gui/button.h"
#include "scene/gui/option_button.h"
#include "scene/gui/texture_rect.h"
#include "../../../algos/mm_algos.h"
void MMTonesEditor::set_value(const Ref<MMTones> &v) {
if (_node == v) {
return;
}
if (_node.is_valid()) {
_node->get_image()->disconnect("changed", this, "on_input_property_changed");
}
_node = v;
if (_node.is_valid()) {
_node->get_image()->connect("changed", this, "on_input_property_changed");
}
on_input_property_changed();
}
Ref<ImageTexture> MMTonesEditor::make_histogram(const Ref<Image> &img) {
ERR_FAIL_COND_V(!img.is_valid(), Ref<ImageTexture>());
Ref<Image> histogram = MMAlgos::generate_histogram(img, HISTOGRAM_IMAGE_SIZE);
Ref<ImageTexture> tex;
tex.instance();
tex->create_from_image(histogram, 0);
return tex;
}
Ref<ImageTexture> MMTonesEditor::make_default_histogram() {
Ref<Image> img;
img.instance();
img->create(HISTOGRAM_IMAGE_SIZE, HISTOGRAM_IMAGE_SIZE, false, Image::FORMAT_RGBA8);
img->fill(Color(1, 1, 1, 1));
return make_histogram(img);
}
MMTonesEditor::MMTonesEditor() {
HBoxContainer *bar = memnew(HBoxContainer);
add_child(bar);
_mode_ob = memnew(OptionButton);
bar->add_child(_mode_ob);
_mode_ob->set_h_size_flags(Control::SIZE_EXPAND_FILL);
_mode_ob->add_item("Luminance", MODE_LUMINANCE);
_mode_ob->add_item("Red", MODE_RED);
_mode_ob->add_item("Green", MODE_GREEN);
_mode_ob->add_item("Blue", MODE_BLUE);
_mode_ob->add_item("Alpha", MODE_ALPHA);
_mode_ob->select(MODE_LUMINANCE);
Button *auto_button = memnew(Button);
bar->add_child(auto_button);
auto_button->set_text("AL");
auto_button->set_tooltip("Set levels automatically");
auto_button->set_v_size_flags(Control::SIZE_SHRINK_CENTER);
Control *spacer = memnew(Control);
spacer->set_custom_minimum_size(Vector2(0, 4));
add_child(spacer);
_histogram_tr = memnew(TextureRect);
_histogram_tr->set_custom_minimum_size(Vector2(0, 100));
_histogram_tr->set_h_size_flags(Control::SIZE_EXPAND_FILL);
add_child(_histogram_tr);
spacer = memnew(Control);
spacer->set_custom_minimum_size(Vector2(0, 4));
add_child(spacer);
}
MMTonesEditor::~MMTonesEditor() {
}
void MMTonesEditor::on_input_property_changed() {
if (!_node.is_valid()) {
_histogram_tr->set_texture(make_default_histogram());
ERR_PRINT("asdasd");
return;
}
Ref<Image> img = _node->get_image()->get_active_image();
if (!img.is_valid()) {
_histogram_tr->set_texture(make_default_histogram());
ERR_PRINT("asdasd2");
return;
}
ERR_PRINT("asdasd3");
_histogram_tr->set_texture(make_histogram(img));
}
void MMTonesEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("on_input_property_changed"), &MMTonesEditor::on_input_property_changed);
}

View File

@ -0,0 +1,48 @@
#ifndef MM_TONES_EDITOR_H
#define MM_TONES_EDITOR_H
#include "core/object/reference.h"
#include "scene/gui/box_container.h"
class MMTones;
class OptionButton;
class TextureRect;
class ImageTexture;
class MMTonesEditor : public VBoxContainer {
GDCLASS(MMTonesEditor, VBoxContainer);
public:
enum Modes {
MODE_LUMINANCE = 0,
MODE_RED,
MODE_GREEN,
MODE_BLUE,
MODE_ALPHA,
};
enum {
HISTOGRAM_IMAGE_SIZE = 256,
};
void set_value(const Ref<MMTones> &v);
Ref<ImageTexture> make_histogram(const Ref<Image> &img);
Ref<ImageTexture> make_default_histogram();
MMTonesEditor();
~MMTonesEditor();
protected:
void on_input_property_changed();
static void _bind_methods();
Ref<MMTones> _node;
OptionButton *_mode_ob;
TextureRect *_histogram_tr;
};
#endif

View File

@ -0,0 +1,11 @@
#include "tones_editor_cursor.h"
MMTonesEditorCursor::MMTonesEditorCursor() {
}
MMTonesEditorCursor::~MMTonesEditorCursor() {
}
void MMTonesEditorCursor::_bind_methods() {
}

View File

@ -0,0 +1,17 @@
#ifndef MM_TONES_EDITOR_CURSOR_H
#define MM_TONES_EDITOR_CURSOR_H
#include "scene/gui/texture_rect.h"
class MMTonesEditorCursor : public TextureRect {
GDCLASS(MMTonesEditorCursor, TextureRect);
public:
MMTonesEditorCursor();
~MMTonesEditorCursor();
protected:
static void _bind_methods();
};
#endif

View File

@ -0,0 +1,149 @@
#include "tones.h"
#include "../../algos/mm_algos.h"
#include "../../editor/mm_graph_node.h"
#include "../mm_material.h"
Ref<MMNodeUniversalProperty> MMTones::get_input() {
return input;
}
void MMTones::set_input(const Ref<MMNodeUniversalProperty> &val) {
input = val;
}
Ref<MMNodeUniversalProperty> MMTones::get_image() {
return image;
}
void MMTones::set_image(const Ref<MMNodeUniversalProperty> &val) {
image = val;
}
Color MMTones::get_in_max() const {
return _in_max;
}
void MMTones::set_in_max(const Color &val) {
_in_max = val;
set_dirty(true);
}
Color MMTones::get_in_mid() const {
return _in_mid;
}
void MMTones::set_in_mid(const Color &val) {
_in_mid = val;
set_dirty(true);
}
Color MMTones::get_in_min() const {
return _in_min;
}
void MMTones::set_in_min(const Color &val) {
_in_min = val;
set_dirty(true);
}
Color MMTones::get_out_max() const {
return _out_max;
}
void MMTones::set_out_max(const Color &val) {
_out_max = val;
set_dirty(true);
}
Color MMTones::get_out_min() const {
return _out_min;
}
void MMTones::set_out_min(const Color &val) {
_out_min = val;
set_dirty(true);
}
void MMTones::_init_properties() {
if (!input.is_valid()) {
input.instance();
input->set_default_type(MMNodeUniversalProperty::DEFAULT_TYPE_COLOR);
input->set_default_value(Color(0, 0, 0, 1));
}
input->set_input_slot_type(MMNodeUniversalProperty::SLOT_TYPE_UNIVERSAL);
input->set_slot_name(">>> Input ");
if (!image.is_valid()) {
image.instance();
image->set_default_type(MMNodeUniversalProperty::DEFAULT_TYPE_IMAGE);
}
//image.input_slot_type = MMNodeUniversalProperty.SLOT_TYPE_FLOAT;
image->set_output_slot_type(MMNodeUniversalProperty::SLOT_TYPE_IMAGE);
//image.force_override = true;
register_input_property(input);
register_output_property(image);
}
void MMTones::_register_methods(MMGraphNode *mm_graph_node) {
mm_graph_node->add_slot_label_universal(input);
mm_graph_node->add_slot_texture_universal(image);
mm_graph_node->add_slot_tones();
//mm_graph_node->add_slot_color("get_in_max", "set_in_max");
//mm_graph_node->add_slot_color("get_in_mid", "set_in_mid");
//mm_graph_node->add_slot_color("get_in_min", "set_in_min");
//mm_graph_node->add_slot_color("get_out_max", "set_out_max");
//mm_graph_node->add_slot_color("get_out_min", "set_out_min");
}
void MMTones::_render(const Ref<MMMaterial> &material) {
Ref<Image> img = render_image(material);
image->set_value(img);
}
Color MMTones::_get_value_for(const Vector2 &uv, const int pseed) {
Color c = input->get_value(uv);
return MMAlgos::adjust_levels(c, _in_min, _in_mid, _in_max, _out_min, _out_max);
}
MMTones::MMTones() {
_in_max = Color(1, 1, 1, 1);
_in_mid = Color(0.5, 0.5, 0.5, 0.5);
_in_min = Color(0, 0, 0, 0);
_out_max = Color(1, 1, 1, 1);
_out_min = Color(0, 0, 0, 0);
}
MMTones::~MMTones() {
}
void MMTones::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_input"), &MMTones::get_input);
ClassDB::bind_method(D_METHOD("set_input", "value"), &MMTones::set_input);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "input", PROPERTY_HINT_RESOURCE_TYPE, "MMNodeUniversalProperty"), "set_input", "get_input");
ClassDB::bind_method(D_METHOD("get_image"), &MMTones::get_image);
ClassDB::bind_method(D_METHOD("set_image", "value"), &MMTones::set_image);
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "image", PROPERTY_HINT_RESOURCE_TYPE, "MMNodeUniversalProperty"), "set_image", "get_image");
ClassDB::bind_method(D_METHOD("get_in_max"), &MMTones::get_in_max);
ClassDB::bind_method(D_METHOD("set_in_max", "value"), &MMTones::set_in_max);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "in_max"), "set_in_max", "get_in_max");
ClassDB::bind_method(D_METHOD("get_in_mid"), &MMTones::get_in_mid);
ClassDB::bind_method(D_METHOD("set_in_mid", "value"), &MMTones::set_in_mid);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "in_mid"), "set_in_mid", "get_in_mid");
ClassDB::bind_method(D_METHOD("get_in_min"), &MMTones::get_in_min);
ClassDB::bind_method(D_METHOD("set_in_min", "value"), &MMTones::set_in_min);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "in_min"), "set_in_min", "get_in_min");
ClassDB::bind_method(D_METHOD("get_out_max"), &MMTones::get_out_max);
ClassDB::bind_method(D_METHOD("set_out_max", "value"), &MMTones::set_out_max);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "out_max"), "set_out_max", "get_out_max");
ClassDB::bind_method(D_METHOD("get_out_min"), &MMTones::get_out_min);
ClassDB::bind_method(D_METHOD("set_out_min", "value"), &MMTones::set_out_min);
ADD_PROPERTY(PropertyInfo(Variant::COLOR, "out_min"), "set_out_min", "get_out_min");
}

View File

@ -0,0 +1,53 @@
#ifndef MM_TONES_H
#define MM_TONES_H
#include "../mm_node.h"
#include "../mm_node_universal_property.h"
class MMTones : public MMNode {
GDCLASS(MMTones, MMNode);
public:
Ref<MMNodeUniversalProperty> get_input();
void set_input(const Ref<MMNodeUniversalProperty> &val);
Ref<MMNodeUniversalProperty> get_image();
void set_image(const Ref<MMNodeUniversalProperty> &val);
Color get_in_max() const;
void set_in_max(const Color &val);
Color get_in_mid() const;
void set_in_mid(const Color &val);
Color get_in_min() const;
void set_in_min(const Color &val);
Color get_out_max() const;
void set_out_max(const Color &val);
Color get_out_min() const;
void set_out_min(const Color &val);
void _init_properties();
void _register_methods(MMGraphNode *mm_graph_node);
void _render(const Ref<MMMaterial> &material);
Color _get_value_for(const Vector2 &uv, const int pseed);
MMTones();
~MMTones();
protected:
static void _bind_methods();
Ref<MMNodeUniversalProperty> image;
Ref<MMNodeUniversalProperty> input;
Color _in_max;
Color _in_mid;
Color _in_min;
Color _out_max;
Color _out_min;
};
#endif

View File

@ -155,6 +155,7 @@ SOFTWARE.
#include "nodes/filter/quantize.h"
#include "nodes/filter/swap_channels.h"
#include "nodes/filter/tonality.h"
#include "nodes/filter/tones.h"
#include "nodes/filter/tones_map.h"
#include "nodes/filter/tones_step.h"
@ -390,6 +391,8 @@ void register_material_maker_types(ModuleRegistrationLevel p_level) {
MMAlgos::register_node_class("Filter", "MMTonesStep");
ClassDB::register_class<MMTonesMap>();
MMAlgos::register_node_class("Filter", "MMTonesMap");
ClassDB::register_class<MMTones>();
MMAlgos::register_node_class("Filter", "MMTones");
}
#if TOOLS_ENABLED