Implemented the gradient node. Made Material Maker's gradient editor work with my setup.

This commit is contained in:
Relintai 2021-10-17 17:18:41 +02:00
parent d23c7b00b8
commit 4282cc8385
7 changed files with 235 additions and 74 deletions

View File

@ -49,7 +49,7 @@ margin_bottom = 600.0
mouse_filter = 2
[node name="AddPopup" parent="Popups" instance=ExtResource( 2 )]
type_folders = PoolStringArray( "res://addons/mat_maker_gd/nodes/filter", "res://addons/mat_maker_gd/nodes/noise", "res://addons/mat_maker_gd/nodes/pattern", "res://addons/mat_maker_gd/nodes/sdf2d", "res://addons/mat_maker_gd/nodes/sdf3d", "res://addons/mat_maker_gd/nodes/simple", "res://addons/mat_maker_gd/nodes/other" )
type_folders = PoolStringArray( "res://addons/mat_maker_gd/nodes/noise", "res://addons/mat_maker_gd/nodes/filter", "res://addons/mat_maker_gd/nodes/gradient", "res://addons/mat_maker_gd/nodes/pattern", "res://addons/mat_maker_gd/nodes/sdf2d", "res://addons/mat_maker_gd/nodes/sdf3d", "res://addons/mat_maker_gd/nodes/simple", "res://addons/mat_maker_gd/nodes/other" )
[connection signal="pressed" from="VBoxContainer/PanelContainer/HBoxContainer/AddButton" to="." method="_on_AddButton_pressed"]
[connection signal="ok_pressed" from="Popups/AddPopup" to="." method="_on_AddPopup_ok_pressed"]

View File

@ -1,6 +1,8 @@
tool
extends GraphNode
var gradient_editor_scene : PackedScene = preload("res://addons/mat_maker_gd/widgets/gradient_editor/gradient_editor.tscn")
var slot_colors : PoolColorArray
var _material : MMMateial = null
@ -20,7 +22,19 @@ func add_slot_texture(getter : String, setter : String) -> int:
properties[slot_idx].append(t.texture)
return slot_idx
func add_slot_gradient() -> int:
var ge : Control = gradient_editor_scene.instance()
var slot_idx : int = add_slot(MMNodeUniversalProperty.SlotTypes.SLOT_TYPE_NONE, MMNodeUniversalProperty.SlotTypes.SLOT_TYPE_NONE, "", "", ge)
ge.set_value(_node)
#ge.texture = _node.call(getter, _material, slot_idx)
#properties[slot_idx].append(ge.texture)
return slot_idx
func add_slot_texture_universal(property : MMNodeUniversalProperty) -> int:
var t : TextureRect = TextureRect.new()

View File

@ -76,7 +76,6 @@ static func circular_gradient_type_4(uv : Vector2, repeat : float, data : PoolRe
return gradient_type_4(Commons.fractf(repeat * 0.15915494309 * atan((uv.x - 0.5) / uv.y - 0.5)), data)
static func gradient_type_1(x : float, data : PoolRealArray) -> Color:
if data.size() % 5 != 0 || data.size() == 0:
return Color()
@ -92,7 +91,7 @@ static func gradient_type_2(x : float, data : PoolRealArray) -> Color:
if data.size() % 5 != 0 || data.size() == 0:
return Color()
for i in range(0, data.size() - 5, 5):
for i in range(0, data.size(), 5):
if x < data[i]:
if i == 0:
return Color(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
@ -108,7 +107,7 @@ static func gradient_type_3(x : float, data : PoolRealArray) -> Color:
if data.size() % 5 != 0 || data.size() == 0:
return Color()
for i in range(0, data.size() - 5, 5):
for i in range(0, data.size(), 5):
if x < data[i]:
if i == 0:
return Color(data[i + 1], data[i + 2], data[i + 3], data[i + 4])
@ -125,7 +124,7 @@ static func gradient_type_4(x : float, data : PoolRealArray) -> Color:
if data.size() % 5 != 0 || data.size() == 0:
return Color()
for i in range(0, data.size() - 5, 5):
for i in range(0, data.size(), 5):
if x < data[i]:
if i == 0:
return Color(data[i + 1], data[i + 2], data[i + 3], data[i + 4])

View File

@ -0,0 +1,116 @@
tool
extends MMNode
var Gradients = preload("res://addons/mat_maker_gd/nodes/common/gradients.gd")
export(Resource) var image : Resource
export(float) var repeat : float = 1
export(float) var rotate : float = 0
export(int) var interpolation_type : int = 1 setget set_interpolation_type, get_interpolation_type
export(PoolRealArray) var points : PoolRealArray = PoolRealArray()
func _init_properties():
if !image:
image = MMNodeUniversalProperty.new()
image.default_type = MMNodeUniversalProperty.MMNodeUniversalPropertyDefaultType.DEFAULT_TYPE_IMAGE
image.output_slot_type = MMNodeUniversalProperty.SlotTypes.SLOT_TYPE_IMAGE
register_output_property(image)
func _register_methods(mm_graph_node) -> void:
mm_graph_node.add_slot_texture_universal(image)
mm_graph_node.add_slot_float("get_repeat", "set_repeat", "repeat")
mm_graph_node.add_slot_float("get_rotate", "set_rotate", "rotate")
mm_graph_node.add_slot_gradient()
func _render(material) -> void:
var img : Image = render_image(material)
image.set_value(img)
func get_value_for(uv : Vector2, pseed : int) -> Color:
if interpolation_type == 0:
return Gradients.normal_gradient_type_1(uv, repeat, rotate, points)
elif interpolation_type == 1:
return Gradients.normal_gradient_type_2(uv, repeat, rotate, points)
elif interpolation_type == 2:
return Gradients.normal_gradient_type_3(uv, repeat, rotate, points)
elif interpolation_type == 3:
return Gradients.normal_gradient_type_4(uv, repeat, rotate, points)
return Color(1, 1, 1, 1)
func get_gradient_color(x : float) -> Color:
if interpolation_type == 0:
return Gradients.gradient_type_1(x, points)
elif interpolation_type == 1:
return Gradients.gradient_type_2(x, points)
elif interpolation_type == 2:
return Gradients.gradient_type_3(x, points)
elif interpolation_type == 3:
return Gradients.gradient_type_4(x, points)
return Color(1, 1, 1, 1)
func get_repeat() -> float:
return repeat
func set_repeat(val : float) -> void:
repeat = val
set_dirty(true)
func get_rotate() -> float:
return rotate
func set_rotate(val : float) -> void:
rotate = val
set_dirty(true)
func get_interpolation_type() -> int:
return interpolation_type
func set_interpolation_type(val : int) -> void:
interpolation_type = val
set_dirty(true)
func get_points() -> PoolRealArray:
return points
func set_points(val : PoolRealArray) -> void:
points = val
set_dirty(true)
func get_point_value(index : int) -> float:
return points[index * 5]
func get_point_color(index : int) -> Color:
var indx : int = index * 5
return Color(points[indx + 1], points[indx + 2], points[indx + 3], points[indx + 4])
func add_point(val : float, color : Color) -> void:
var s : int = points.size()
points.resize(s + 5)
points[s] = val
points[s + 1] = color.r
points[s + 2] = color.g
points[s + 3] = color.b
points[s + 4] = color.a
set_dirty(true)
func get_point_count() -> int:
return points.size() / 5
func clear() -> void:
points.resize(0)
set_dirty(true)

View File

@ -71,53 +71,63 @@ export var embedded : bool = true
signal updated(value)
func _ready() -> void:
$Gradient.material = $Gradient.material.duplicate(true)
#set_value(MMGradient.new())
func _init():
connect("resized", self, "on_resized")
func get_gradient_from_data(data):
if typeof(data) == TYPE_ARRAY:
return data
elif typeof(data) == TYPE_DICTIONARY:
if data.has("parameters") and data.parameters.has("gradient"):
return data.parameters.gradient
if data.has("type") and data.type == "Gradient":
return data
return null
#func get_gradient_from_data(data):
# if typeof(data) == TYPE_ARRAY:
# return data
# elif typeof(data) == TYPE_DICTIONARY:
# if data.has("parameters") and data.parameters.has("gradient"):
# return data.parameters.gradient
# if data.has("type") and data.type == "Gradient":
# return data
# return null
func get_drag_data(_position : Vector2):
var data = 0#MMType.serialize_value(value)
var preview = ColorRect.new()
preview.rect_size = Vector2(64, 24)
preview.material = $Gradient.material
set_drag_preview(preview)
return data
func can_drop_data(_position : Vector2, data) -> bool:
return get_gradient_from_data(data) != null
func drop_data(_position : Vector2, data) -> void:
var gradient = get_gradient_from_data(data)
#if gradient != null:
#set_value(MMType.deserialize_value(gradient))
#func get_drag_data(_position : Vector2):
# var data = 0#MMType.serialize_value(value)
# var preview = ColorRect.new()
# preview.rect_size = Vector2(64, 24)
# preview.material = $Gradient.material
# set_drag_preview(preview)
# return data
#
#func can_drop_data(_position : Vector2, data) -> bool:
# return get_gradient_from_data(data) != null
#
#func drop_data(_position : Vector2, data) -> void:
# var gradient = get_gradient_from_data(data)
# #if gradient != null:
# #set_value(MMType.deserialize_value(gradient))
func set_value(v) -> void:
value = v
update_preview()
call_deferred("update_cursors")
func update_cursors() -> void:
for c in get_children():
if c is GradientCursor:
remove_child(c)
c.free()
for p in value.points:
add_cursor(p.v*(rect_size.x-GradientCursor.WIDTH), p.c)
$Interpolation.selected = value.interpolation
update_shader()
var vs : int = value.get_point_count()
for i in range(vs):
add_cursor(value.get_point_value(i) * (rect_size.x-GradientCursor.WIDTH), value.get_point_color(i))
$Interpolation.selected = value.interpolation_type
func update_value() -> void:
value.clear()
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()
var sc : Array = get_sorted_cursors()
for c in sc:
value.add_point(c.rect_position.x/(rect_size.x-GradientCursor.WIDTH), c.color)
update_preview()
func add_cursor(x, color) -> void:
var cursor = GradientCursor.new()
@ -132,7 +142,7 @@ func _gui_input(ev) -> void:
add_cursor(p, get_gradient_color(p))
update_value()
elif embedded:
var popup = load("res://material_maker/widgets/gradient_editor/gradient_popup.tscn").instance()
var popup = load("res://addons/mat_maker_gd/widgets/gradient_editor/gradient_popup.tscn").instance()
add_child(popup)
var popup_size = popup.rect_size
popup.popup(Rect2(ev.global_position, Vector2(0, 0)))
@ -166,20 +176,48 @@ func get_sorted_cursors() -> Array:
array.sort_custom(GradientCursor, "sort")
return array
func get_gradient_color(x) -> Color:
return value.get_color(x / (rect_size.x - GradientCursor.WIDTH))
func generate_preview_image() -> void:
var tex : ImageTexture = $Gradient.texture
if !tex:
tex = ImageTexture.new()
$Gradient.texture = tex
var img : Image = tex.get_data()
var w : float = $Gradient.rect_size.x
var h : float = $Gradient.rect_size.y
if !img:
img = Image.new()
func update_shader() -> void:
var shader
shader = "shader_type canvas_item;\n"
var params = value.get_shader_params("")
for sp in params.keys():
shader += "uniform float "+sp+" = "+str(params[sp])+";\n"
shader += value.get_shader("")
shader += "void fragment() { COLOR = _gradient_fct(UV.x); }"
$Gradient.material.shader.set_code(shader)
emit_signal("updated", value)
if img.get_size().x != w || img.get_size().y != h:
img.create(w, h, false, Image.FORMAT_RGBA8)
img.lock()
for i in range(w):
var x : float = float(i) / float(w)
var col : Color = value.get_gradient_color(x)
for j in range(h):
img.set_pixel(i, j, col)
img.unlock()
tex.create_from_image(img, 0)
func get_gradient_color(x) -> Color:
return value.get_gradient_color(x / (rect_size.x - GradientCursor.WIDTH))
func update_preview() -> void:
call_deferred("generate_preview_image")
func _on_Interpolation_item_selected(ID) -> void:
value.interpolation = ID
update_shader()
value.interpolation_type = ID
update_preview()
func on_resized() -> void:
if value:
update_preview()
call_deferred("update_cursors")

View File

@ -1,4 +1,4 @@
[gd_scene load_steps=12 format=2]
[gd_scene load_steps=10 format=2]
[ext_resource path="res://addons/mat_maker_gd/widgets/gradient_editor/gradient_editor.gd" type="Script" id=1]
[ext_resource path="res://addons/mat_maker_gd/icons/icons.tres" type="Texture" id=2]
@ -13,36 +13,25 @@ void fragment() {
[sub_resource type="ShaderMaterial" id=2]
shader = SubResource( 1 )
[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(1.000000000,1.000000000,1.000000000,1.000000000);
}
void fragment() { COLOR = gradient(UV.x); }"
[sub_resource type="ShaderMaterial" id=4]
shader = SubResource( 3 )
[sub_resource type="Theme" id=5]
[sub_resource type="AtlasTexture" id=6]
flags = 7
atlas = ExtResource( 2 )
region = Rect2( 96, 0, 32, 16 )
[sub_resource type="AtlasTexture" id=7]
flags = 7
atlas = ExtResource( 2 )
region = Rect2( 64, 0, 32, 16 )
[sub_resource type="AtlasTexture" id=8]
flags = 7
atlas = ExtResource( 2 )
region = Rect2( 64, 16, 32, 16 )
[sub_resource type="AtlasTexture" id=9]
flags = 7
atlas = ExtResource( 2 )
region = Rect2( 96, 16, 32, 16 )
@ -64,9 +53,11 @@ margin_right = -4.0
margin_bottom = 15.0
rect_min_size = Vector2( 112, 17 )
mouse_filter = 2
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Gradient" type="ColorRect" parent="."]
material = SubResource( 4 )
[node name="Gradient" type="TextureRect" parent="."]
anchor_right = 1.0
margin_left = 4.0
margin_right = -4.0
@ -74,6 +65,9 @@ margin_bottom = 15.0
rect_min_size = Vector2( 112, 17 )
mouse_filter = 2
theme = SubResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Interpolation" type="OptionButton" parent="."]
margin_left = 0.418457

View File

@ -3,7 +3,6 @@
[ext_resource path="res://addons/mat_maker_gd/widgets/gradient_editor/gradient_popup.gd" type="Script" id=1]
[ext_resource path="res://addons/mat_maker_gd/widgets/gradient_editor/gradient_editor.tscn" type="PackedScene" id=2]
[sub_resource type="StyleBoxFlat" id=1]
bg_color = Color( 0, 0, 0.25098, 0.752941 )
@ -27,5 +26,6 @@ margin_top = 10.0
margin_right = -10.0
margin_bottom = -10.0
embedded = false
[connection signal="popup_hide" from="." to="." method="_on_GradientPopup_popup_hide"]
[connection signal="updated" from="Panel/Control" to="." method="_on_Control_updated"]