From f664a54e4b71b33fc2c1fbf3f519d9952312084b Mon Sep 17 00:00:00 2001 From: RodZill4 Date: Wed, 30 Oct 2019 22:57:51 +0100 Subject: [PATCH] Updated gradient with a choice of 4 interpolation options --- addons/material_maker/icons/icons.svg | 43 +++++++++- addons/material_maker/types/gradient.gd | 86 +++++++++++++++---- .../material_maker/widgets/gradient_editor.gd | 18 ++-- .../widgets/gradient_editor.tscn | 46 ++++++++-- 4 files changed, 160 insertions(+), 33 deletions(-) diff --git a/addons/material_maker/icons/icons.svg b/addons/material_maker/icons/icons.svg index 8cf3cee..1cc7e5f 100644 --- a/addons/material_maker/icons/icons.svg +++ b/addons/material_maker/icons/icons.svg @@ -10,9 +10,9 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="64" + width="128" height="64" - viewBox="0 0 64 64" + viewBox="0 0 128 64" version="1.1" id="svg8" inkscape:version="0.92.3 (2405546, 2018-03-11)" @@ -49,8 +49,8 @@ inkscape:pageopacity="0.0" inkscape:pageshadow="2" inkscape:zoom="14.304427" - inkscape:cx="23.663017" - inkscape:cy="5.4603811" + inkscape:cx="79.150133" + inkscape:cy="47.863625" inkscape:document-units="px" inkscape:current-layer="layer1" showgrid="true" @@ -358,5 +358,40 @@ id="path4561" d="m 33.500409,335.78733 4.34961,-0.0488 0.123047,-6.82227 h 4.27539 l 0.125,6.82227 4.34961,0.0488 -6.611328,6.8457 z" style="fill:#ffffff;fill-opacity:0.84322037;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" /> + + + + + + diff --git a/addons/material_maker/types/gradient.gd b/addons/material_maker/types/gradient.gd index 5ec0e59..8eb5f52 100644 --- a/addons/material_maker/types/gradient.gd +++ b/addons/material_maker/types/gradient.gd @@ -6,6 +6,7 @@ class CustomSorter: return a.v < b.v var points = [ { v=0.0, c=Color(0.0, 0.0, 0.0, 0.0) }, { v=1.0, c=Color(1.0, 1.0, 1.0, 1.0) } ] +var interpolation = 1 var sorted = true func to_string() -> String: @@ -59,22 +60,69 @@ func get_shader(name) -> String: sort() var shader shader = "vec4 "+name+"(float x) {\n" - if points.size() > 0: - shader += " if (x < %.9f) {\n" % points[0].v - shader += " return "+gcis(points[0].c)+";\n" - var s = points.size()-1 - for i in range(s): - var p0 = points[i].v - var c0 = points[i].c - var p1mp0 = points[i+1].v-p0 - var c1mc0 = points[i+1].c-c0 - if p1mp0 > 0: - shader += " } else if (x < %.9f) {\n" % points[i+1].v - shader += " return %s+x*%s;\n" % [gcis(c0-c1mc0*(p0/p1mp0)), gcis(c1mc0/p1mp0)] - shader += " }\n" - shader += " return "+gcis(points[s].c)+";\n" - else: - shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" + match interpolation: + 0: + if points.size() > 0: + shader += " if (x < %.9f) {\n" % (0.5*(points[0].v + points[1].v)) + shader += " return "+gcis(points[0].c)+";\n" + var s = points.size()-1 + for i in range(s): + var p0 = points[i].v + var c0 = points[i].c + var p1mp0 = points[i+1].v-p0 + var c1mc0 = points[i+1].c-c0 + if p1mp0 > 0: + shader += " } else if (x < %.9f) {\n" % (0.5*(points[i].v + points[i+1].v)) + shader += " return "+gcis(points[i].c)+";\n" + shader += " }\n" + shader += " return "+gcis(points[s].c)+";\n" + else: + shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" + 1, 2: + if points.size() > 0: + shader += " if (x < %.9f) {\n" % points[0].v + shader += " return "+gcis(points[0].c)+";\n" + var s = points.size()-1 + for i in range(s): + var p1mp0 = points[i+1].v-points[i].v + if p1mp0 > 0: + shader += " } else if (x < %.9f) {\n" % points[i+1].v + var function = "(" if interpolation == 1 else "0.5-0.5*cos(3.14159265359*" + shader += " return mix(%s, %s, %s(x-%.9f)/%.9f));\n" % [ gcis(points[i].c), gcis(points[i+1].c), function, points[i].v, p1mp0 ] + shader += " }\n" + shader += " return "+gcis(points[s].c)+";\n" + else: + shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" + 3: + if points.size() > 0: + shader += " if (x < %.9f) {\n" % points[0].v + shader += " return "+gcis(points[0].c)+";\n" + var s = points.size()-1 + for i in range(s): + var p1mp0 = points[i+1].v-points[i].v + if p1mp0 > 0: + shader += " } else if (x < %.9f) {\n" % points[i+1].v + var dx : String = "(x-%.9f)/%.9f" % [ points[i].v, p1mp0 ] + var b : String = "mix(%s, %s, %s)" % [ gcis(points[i].c), gcis(points[i+1].c), dx ] + if i > 0 and points[i-1].v < points[i].v: + var a : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i-1].c), gcis(points[i].c), points[i-1].v, points[i].v-points[i-1].v ] + if i < s-1 and points[i+1].v < points[i+2].v: + var c : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i+1].c), gcis(points[i+2].c), points[i+1].v, points[i+2].v-points[i+1].v ] + var ac : String = "mix("+a+", "+c+", 0.5-0.5*cos(3.14159265359*"+dx+"))" + shader += " return 0.5*("+b+" + "+ac+");\n" + else: + shader += " return mix("+a+", "+b+", 0.5+0.5*"+dx+");\n" + elif i < s-1 and points[i+1].v < points[i+2].v: + var c : String = "mix(%s, %s, (x-%.9f)/%.9f)" % [ gcis(points[i+1].c), gcis(points[i+2].c), points[i+1].v, points[i+2].v-points[i+1].v ] + shader += " return mix("+c+", "+b+", 1.0-0.5*"+dx+");\n" + else: + shader += " return "+b+";\n" + shader += " }\n" + shader += " return "+gcis(points[s].c)+";\n" + else: + shader += " return vec4(0.0, 0.0, 0.0, 1.0);\n" + _: + print("interpolation: "+str(interpolation)) shader += "}\n" return shader @@ -83,7 +131,7 @@ func serialize() -> Dictionary: var rv = [] for p in points: rv.append({ pos=p.v, r=p.c.r, g=p.c.g, b=p.c.b, a=p.c.a }) - rv = { type="Gradient", points=rv } + rv = { type="Gradient", points=rv, interpolation=interpolation } return rv func deserialize(v) -> void: @@ -96,6 +144,10 @@ func deserialize(v) -> void: for i in v.points: if !i.has("a"): i.a = 1.0 add_point(i.pos, Color(i.r, i.g, i.b, i.a)) + if v.has("interpolation"): + interpolation = int(v.interpolation) + else: + interpolation = 1 elif typeof(v) == TYPE_OBJECT and v.get_script() == get_script(): clear() for p in v.points: diff --git a/addons/material_maker/widgets/gradient_editor.gd b/addons/material_maker/widgets/gradient_editor.gd index d264d38..6aface8 100644 --- a/addons/material_maker/widgets/gradient_editor.gd +++ b/addons/material_maker/widgets/gradient_editor.gd @@ -61,13 +61,14 @@ func set_value(v) -> void: c.free() for p in value.points: add_cursor(p.v*(rect_size.x-GradientCursor.WIDTH), p.c) + $Interpolation.selected = value.interpolation update_shader() func update_value() -> void: value.clear() - for p in get_children(): - if p != $Gradient and p != $Background: - value.add_point(p.rect_position.x/(rect_size.x-GradientCursor.WIDTH), p.color) + for c in get_children(): + if c is GradientCursor: + value.add_point(c.rect_position.x/(rect_size.x-GradientCursor.WIDTH), c.color) update_shader() func add_cursor(x, color) -> void: @@ -108,9 +109,10 @@ func _on_Popup_popup_hide() -> void: # Calculating a color from the gradient and generating the shader func get_sorted_cursors() -> Array: - var array = get_children() - array.erase($Gradient) - array.erase($Background) + var array = [] + for c in get_children(): + if c is GradientCursor: + array.append(c) array.sort_custom(GradientCursor, "sort") return array @@ -124,3 +126,7 @@ func update_shader() -> void: shader += "void fragment() { COLOR = gradient(UV.x); }" $Gradient.material.shader.set_code(shader) emit_signal("updated", value) + +func _on_Interpolation_item_selected(ID): + value.interpolation = ID + update_shader() diff --git a/addons/material_maker/widgets/gradient_editor.tscn b/addons/material_maker/widgets/gradient_editor.tscn index 841c50a..b10c73b 100644 --- a/addons/material_maker/widgets/gradient_editor.tscn +++ b/addons/material_maker/widgets/gradient_editor.tscn @@ -1,6 +1,7 @@ -[gd_scene load_steps=7 format=2] +[gd_scene load_steps=12 format=2] [ext_resource path="res://addons/material_maker/widgets/gradient_editor.gd" type="Script" id=1] +[ext_resource path="res://addons/material_maker/icons/icons.svg" type="Texture" id=2] [sub_resource type="Shader" id=1] code = "shader_type canvas_item; @@ -12,21 +13,43 @@ void fragment() { [sub_resource type="ShaderMaterial" id=2] shader = SubResource( 1 ) -[sub_resource type="Shader" id=6] +[sub_resource type="Shader" id=3] code = "shader_type canvas_item; vec4 gradient(float x) { if (x < 0.000000000) { return vec4(0.000000000,0.000000000,0.000000000,0.000000000); + } else if (x < 1.000000000) { + return (mix(vec4(0.000000000,0.000000000,0.000000000,0.000000000), vec4(1.000000000,1.000000000,1.000000000,1.000000000), (x-0.000000000)/1.000000000)); } - return vec4(0.000000000,0.000000000,0.000000000,0.000000000); + return vec4(1.000000000,1.000000000,1.000000000,1.000000000); } void fragment() { COLOR = gradient(UV.x); }" -[sub_resource type="ShaderMaterial" id=7] -shader = SubResource( 6 ) +[sub_resource type="ShaderMaterial" id=4] +shader = SubResource( 3 ) [sub_resource type="Theme" id=5] +[sub_resource type="AtlasTexture" id=6] +flags = 4 +atlas = ExtResource( 2 ) +region = Rect2( 96, 0, 32, 16 ) + +[sub_resource type="AtlasTexture" id=7] +flags = 4 +atlas = ExtResource( 2 ) +region = Rect2( 64, 0, 32, 16 ) + +[sub_resource type="AtlasTexture" id=8] +flags = 4 +atlas = ExtResource( 2 ) +region = Rect2( 64, 16, 32, 16 ) + +[sub_resource type="AtlasTexture" id=9] +flags = 4 +atlas = ExtResource( 2 ) +region = Rect2( 96, 16, 32, 16 ) + [node name="Control" type="Control"] margin_right = 120.0 margin_bottom = 30.0 @@ -43,7 +66,7 @@ rect_min_size = Vector2( 112, 17 ) mouse_filter = 2 [node name="Gradient" type="ColorRect" parent="."] -material = SubResource( 7 ) +material = SubResource( 4 ) anchor_right = 1.0 margin_left = 4.0 margin_right = -4.0 @@ -64,4 +87,15 @@ margin_top = 4.0 margin_right = 4.0 margin_bottom = 4.0 rect_scale = Vector2( 0.75, 0.75 ) + +[node name="Interpolation" type="OptionButton" parent="."] +margin_left = 0.418457 +margin_top = -2.90374 +margin_right = 73.4185 +margin_bottom = 19.0963 +rect_scale = Vector2( 0.5, 0.5 ) +icon = SubResource( 6 ) +items = [ "", SubResource( 7 ), false, 0, null, "", SubResource( 6 ), false, 1, null, "", SubResource( 8 ), false, 2, null, "", SubResource( 9 ), false, 3, null ] +selected = 1 [connection signal="popup_hide" from="Gradient/Popup" to="." method="_on_Popup_popup_hide"] +[connection signal="item_selected" from="Interpolation" to="." method="_on_Interpolation_item_selected"]