mirror of
https://github.com/Relintai/material-maker.git
synced 2024-11-13 06:27:18 +01:00
New gradient editor, more image node progress
Added a gradient editor (should be ready for integration in Colorize node) The image in the Image node can be modified (but will not be saved yet)
This commit is contained in:
parent
d04a319944
commit
46adb434bf
Binary file not shown.
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 1.0 MiB |
@ -1,14 +1,17 @@
|
|||||||
tool
|
tool
|
||||||
extends "res://addons/procedural_material/node_base.gd"
|
extends "res://addons/procedural_material/node_base.gd"
|
||||||
|
|
||||||
var rows
|
var file_path
|
||||||
|
|
||||||
func _ready():
|
func _ready():
|
||||||
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
|
set_slot(0, false, 0, Color(0.5, 0.5, 1), true, 0, Color(0.5, 0.5, 1))
|
||||||
|
|
||||||
func set_texture(path):
|
func set_texture(path):
|
||||||
|
file_path = path
|
||||||
var texture = ImageTexture.new()
|
var texture = ImageTexture.new()
|
||||||
texture.load(path)
|
texture.load(path)
|
||||||
|
$TextureButton.texture_normal = texture
|
||||||
|
get_parent().get_parent().generate_shader()
|
||||||
|
|
||||||
func get_textures():
|
func get_textures():
|
||||||
var list = {}
|
var list = {}
|
||||||
@ -26,3 +29,13 @@ func _get_shader_code(uv):
|
|||||||
rv.code = "vec3 "+name+"_"+str(variant_index)+"_rgb = texture("+name+"_tex, "+uv+").rgb;\n"
|
rv.code = "vec3 "+name+"_"+str(variant_index)+"_rgb = texture("+name+"_tex, "+uv+").rgb;\n"
|
||||||
rv.rgb = name+"_"+str(variant_index)+"_rgb"
|
rv.rgb = name+"_"+str(variant_index)+"_rgb"
|
||||||
return rv
|
return rv
|
||||||
|
|
||||||
|
func _on_TextureButton_pressed():
|
||||||
|
var dialog = EditorFileDialog.new()
|
||||||
|
add_child(dialog)
|
||||||
|
dialog.access = EditorFileDialog.ACCESS_FILESYSTEM
|
||||||
|
dialog.mode = EditorFileDialog.MODE_OPEN_FILE
|
||||||
|
dialog.add_filter("*.png;PNG image")
|
||||||
|
dialog.add_filter("*.jpg;JPG image")
|
||||||
|
dialog.connect("file_selected", self, "set_texture")
|
||||||
|
dialog.popup_centered()
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
[sub_resource type="Theme" id=1]
|
[sub_resource type="Theme" id=1]
|
||||||
|
|
||||||
|
|
||||||
[node name="Image" type="GraphNode" index="0"]
|
[node name="Image" type="GraphNode"]
|
||||||
|
|
||||||
anchor_left = 0.0
|
anchor_left = 0.0
|
||||||
anchor_top = 0.0
|
anchor_top = 0.0
|
||||||
@ -22,6 +22,7 @@ mouse_filter = 1
|
|||||||
mouse_default_cursor_shape = 0
|
mouse_default_cursor_shape = 0
|
||||||
size_flags_horizontal = 1
|
size_flags_horizontal = 1
|
||||||
size_flags_vertical = 1
|
size_flags_vertical = 1
|
||||||
|
size_flags_stretch_ratio = 0.13
|
||||||
theme = SubResource( 1 )
|
theme = SubResource( 1 )
|
||||||
title = "Image"
|
title = "Image"
|
||||||
offset = Vector2( 0, 0 )
|
offset = Vector2( 0, 0 )
|
||||||
@ -37,7 +38,7 @@ slot/0/right_enabled = true
|
|||||||
slot/0/right_type = 0
|
slot/0/right_type = 0
|
||||||
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
slot/0/right_color = Color( 0.5, 0.5, 1, 1 )
|
||||||
script = ExtResource( 1 )
|
script = ExtResource( 1 )
|
||||||
_sections_unfolded = [ "Theme", "slot" ]
|
_sections_unfolded = [ "Mouse", "Size Flags", "Theme" ]
|
||||||
|
|
||||||
[node name="TextureButton" type="TextureButton" parent="." index="0"]
|
[node name="TextureButton" type="TextureButton" parent="." index="0"]
|
||||||
|
|
||||||
@ -51,7 +52,7 @@ margin_right = 80.0
|
|||||||
margin_bottom = 88.0
|
margin_bottom = 88.0
|
||||||
rect_min_size = Vector2( 64, 64 )
|
rect_min_size = Vector2( 64, 64 )
|
||||||
rect_pivot_offset = Vector2( 0, 0 )
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
rect_clip_content = false
|
rect_clip_content = true
|
||||||
focus_mode = 2
|
focus_mode = 2
|
||||||
mouse_filter = 0
|
mouse_filter = 0
|
||||||
mouse_default_cursor_shape = 0
|
mouse_default_cursor_shape = 0
|
||||||
@ -62,9 +63,12 @@ enabled_focus_mode = 2
|
|||||||
shortcut = null
|
shortcut = null
|
||||||
group = null
|
group = null
|
||||||
texture_normal = ExtResource( 2 )
|
texture_normal = ExtResource( 2 )
|
||||||
|
expand = true
|
||||||
stretch_mode = 5
|
stretch_mode = 5
|
||||||
_sections_unfolded = [ "Rect", "Textures" ]
|
_sections_unfolded = [ "Rect", "Textures" ]
|
||||||
|
|
||||||
[connection signal="close_request" from="." to="." method="queue_free"]
|
[connection signal="close_request" from="." to="." method="queue_free"]
|
||||||
|
|
||||||
|
[connection signal="pressed" from="TextureButton" to="." method="_on_TextureButton_pressed"]
|
||||||
|
|
||||||
|
|
||||||
|
File diff suppressed because one or more lines are too long
122
addons/procedural_material/widgets/gradient_editor.gd
Normal file
122
addons/procedural_material/widgets/gradient_editor.gd
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
extends Control
|
||||||
|
|
||||||
|
class GradientCursor:
|
||||||
|
extends ColorRect
|
||||||
|
|
||||||
|
const WIDTH = 10
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
rect_position = Vector2(0, 15)
|
||||||
|
rect_size = Vector2(WIDTH, 20)
|
||||||
|
|
||||||
|
func _gui_input(ev):
|
||||||
|
if ev is InputEventMouseButton && ev.button_index == 1 && ev.doubleclick:
|
||||||
|
get_parent().select_color(self)
|
||||||
|
elif ev is InputEventMouseMotion && (ev.button_mask & 1) != 0:
|
||||||
|
rect_position.x += ev.relative.x
|
||||||
|
rect_position.x = min(max(0, rect_position.x), get_parent().rect_size.x-rect_size.x)
|
||||||
|
get_parent().update_shader()
|
||||||
|
|
||||||
|
func get_position():
|
||||||
|
return rect_position.x / (get_parent().rect_size.x - WIDTH)
|
||||||
|
|
||||||
|
func set_color(c):
|
||||||
|
color = c
|
||||||
|
get_parent().update_shader()
|
||||||
|
|
||||||
|
static func sort(a, b):
|
||||||
|
if a.get_position() < b.get_position():
|
||||||
|
return true
|
||||||
|
return false
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
$Gradient.material = $Gradient.material.duplicate(true)
|
||||||
|
add_cursor(0, Color(0, 0, 0))
|
||||||
|
add_cursor(rect_size.x-GradientCursor.WIDTH, Color(1, 1, 1))
|
||||||
|
|
||||||
|
func add_cursor(x, color):
|
||||||
|
var cursor = GradientCursor.new()
|
||||||
|
add_child(cursor)
|
||||||
|
cursor.rect_position.x = x
|
||||||
|
cursor.color = color
|
||||||
|
update_shader()
|
||||||
|
|
||||||
|
func _gui_input(ev):
|
||||||
|
if ev is InputEventMouseButton && ev.button_index == 1 && ev.doubleclick && ev.position.y > 15:
|
||||||
|
add_cursor(ev.position.x, get_color(ev.position.x))
|
||||||
|
|
||||||
|
# Showing a color picker popup to change a cursor's color
|
||||||
|
|
||||||
|
var active_cursor
|
||||||
|
|
||||||
|
func select_color(cursor):
|
||||||
|
active_cursor = cursor
|
||||||
|
$Gradient/Popup/ColorPicker.connect("color_changed", cursor, "set_color")
|
||||||
|
$Gradient/Popup.popup()
|
||||||
|
|
||||||
|
func _on_Popup_popup_hide():
|
||||||
|
$Gradient/Popup/ColorPicker.disconnect("color_changed", active_cursor, "set_color")
|
||||||
|
|
||||||
|
# Calculating a color from the gradient and generating the shader
|
||||||
|
|
||||||
|
func get_sorted_cursors():
|
||||||
|
var array = get_children()
|
||||||
|
array.erase($Gradient)
|
||||||
|
array.sort_custom(GradientCursor, "sort")
|
||||||
|
return array
|
||||||
|
|
||||||
|
func get_color(x):
|
||||||
|
var array = get_sorted_cursors()
|
||||||
|
x = x / (rect_size.x - array[0].rect_size.x)
|
||||||
|
if x < array[0].get_position():
|
||||||
|
return array[0].color
|
||||||
|
for i in range(array.size()-1):
|
||||||
|
if x < array[i+1].get_position():
|
||||||
|
var p0 = array[i].get_position()
|
||||||
|
var c0 = array[i].color
|
||||||
|
var p1 = array[i+1].get_position()
|
||||||
|
var c1 = array[i+1].color
|
||||||
|
return c0 + (c1-c0) * (x-p0) / (p1-p0)
|
||||||
|
return array[array.size()-1].color
|
||||||
|
|
||||||
|
# get_color_in_shader
|
||||||
|
func gcis(color):
|
||||||
|
return "vec3(%.1f,%.1f,%.1f)" % [color.r, color.g, color.b]
|
||||||
|
|
||||||
|
func get_shader(name):
|
||||||
|
var array = get_sorted_cursors()
|
||||||
|
var shader
|
||||||
|
shader = "vec3 "+name+"(float x) {\n"
|
||||||
|
shader += " if (x < %.1f) {\n" % array[0].get_position()
|
||||||
|
shader += " return "+gcis(array[0].color)+";\n"
|
||||||
|
for i in range(array.size()-1):
|
||||||
|
var p0 = array[i].get_position()
|
||||||
|
var c0 = array[i].color
|
||||||
|
var p1mp0 = array[i+1].get_position()-p0
|
||||||
|
var c1mc0 = array[i+1].color-c0
|
||||||
|
if p1mp0 > 0:
|
||||||
|
shader += " } else if (x < %.1f) {\n" % array[i+1].get_position()
|
||||||
|
shader += " return %s+x*%s;\n" % [gcis(c0-c1mc0*(p0/p1mp0)), gcis(c1mc0/p1mp0)]
|
||||||
|
shader += " }\n"
|
||||||
|
shader += " return "+gcis(array[array.size()-1].color)+";\n"
|
||||||
|
shader += "}\n"
|
||||||
|
return shader
|
||||||
|
|
||||||
|
func update_shader():
|
||||||
|
var shader
|
||||||
|
shader = "shader_type canvas_item;\n"
|
||||||
|
shader += get_shader("gradient")
|
||||||
|
shader += "void fragment() { COLOR = vec4(gradient((UV.x-%.1f)*%.1f), 1.0); }" % [ 0.5*GradientCursor.WIDTH/rect_size.x, (rect_size.x-GradientCursor.WIDTH)/rect_size.x ]
|
||||||
|
$Gradient.material.shader.set_code(shader)
|
||||||
|
|
||||||
|
func serialize():
|
||||||
|
var rv = []
|
||||||
|
for c in get_sorted_cursors():
|
||||||
|
rv.append({ pos= c.get_position(), r= c.color.r, g= c.color.g, b= c.color.b })
|
||||||
|
return rv
|
||||||
|
|
||||||
|
func deserialize(v):
|
||||||
|
for c in get_sorted_cursors():
|
||||||
|
queue_free(c)
|
||||||
|
for i in v:
|
||||||
|
add_cursor(i.pos*(rect_size.x-GradientCursor.WIDTH), Color(i.r, i.g, i.b))
|
109
addons/procedural_material/widgets/gradient_editor.tscn
Normal file
109
addons/procedural_material/widgets/gradient_editor.tscn
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
[gd_scene load_steps=4 format=2]
|
||||||
|
|
||||||
|
[ext_resource path="res://addons/procedural_material/widgets/gradient_editor.gd" type="Script" id=1]
|
||||||
|
|
||||||
|
[sub_resource type="Shader" id=1]
|
||||||
|
|
||||||
|
code = "shader_type canvas_item;
|
||||||
|
|
||||||
|
vec3 gradient(float x) {
|
||||||
|
if (x < 0.2) {
|
||||||
|
return vec3(0.1);
|
||||||
|
} else if (x < 0.8) {
|
||||||
|
return vec3(0.1)+(x-0.2)*vec3(0.7);
|
||||||
|
}
|
||||||
|
return vec3(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
void fragment() { COLOR = vec4(gradient(UV.x), 1.0); }
|
||||||
|
"
|
||||||
|
|
||||||
|
[sub_resource type="ShaderMaterial" id=2]
|
||||||
|
|
||||||
|
render_priority = 0
|
||||||
|
shader = SubResource( 1 )
|
||||||
|
|
||||||
|
[node name="Control" type="Control" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 24.0
|
||||||
|
margin_top = 14.0
|
||||||
|
margin_right = 144.0
|
||||||
|
margin_bottom = 44.0
|
||||||
|
rect_min_size = Vector2( 100, 30 )
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
script = ExtResource( 1 )
|
||||||
|
_sections_unfolded = [ "Rect" ]
|
||||||
|
|
||||||
|
[node name="Gradient" type="ColorRect" parent="." index="0"]
|
||||||
|
|
||||||
|
material = SubResource( 2 )
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_right = 120.0
|
||||||
|
margin_bottom = 20.0
|
||||||
|
rect_min_size = Vector2( 120, 20 )
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
color = Color( 1, 1, 1, 1 )
|
||||||
|
_sections_unfolded = [ "Material" ]
|
||||||
|
|
||||||
|
[node name="Popup" type="Popup" parent="Gradient" index="0"]
|
||||||
|
|
||||||
|
visible = false
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 47.0
|
||||||
|
margin_top = 33.0
|
||||||
|
margin_right = 353.0
|
||||||
|
margin_bottom = 475.0
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 0
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
popup_exclusive = false
|
||||||
|
|
||||||
|
[node name="ColorPicker" type="ColorPicker" parent="Gradient/Popup" index="0"]
|
||||||
|
|
||||||
|
anchor_left = 0.0
|
||||||
|
anchor_top = 0.0
|
||||||
|
anchor_right = 0.0
|
||||||
|
anchor_bottom = 0.0
|
||||||
|
margin_left = 4.0
|
||||||
|
margin_top = 4.0
|
||||||
|
margin_right = 302.0
|
||||||
|
margin_bottom = 462.0
|
||||||
|
rect_scale = Vector2( 0.75, 0.75 )
|
||||||
|
rect_pivot_offset = Vector2( 0, 0 )
|
||||||
|
rect_clip_content = false
|
||||||
|
mouse_filter = 1
|
||||||
|
mouse_default_cursor_shape = 0
|
||||||
|
size_flags_horizontal = 1
|
||||||
|
size_flags_vertical = 1
|
||||||
|
alignment = 0
|
||||||
|
color = Color( 1, 1, 1, 1 )
|
||||||
|
edit_alpha = false
|
||||||
|
raw_mode = false
|
||||||
|
_sections_unfolded = [ "Rect" ]
|
||||||
|
|
||||||
|
[connection signal="popup_hide" from="Gradient/Popup" to="." method="_on_Popup_popup_hide"]
|
||||||
|
|
||||||
|
|
14
addons/procedural_material/widgets/gradient_editor_cursor.gd
Normal file
14
addons/procedural_material/widgets/gradient_editor_cursor.gd
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
tool
|
||||||
|
extends ColorRect
|
||||||
|
|
||||||
|
func _ready():
|
||||||
|
pass
|
||||||
|
|
||||||
|
func _on_gui_input(ev):
|
||||||
|
if ev is InputEventMouseButton && ev.button_index == 1 && ev.doubleclick:
|
||||||
|
var dialog = ColorPicker.new()
|
||||||
|
add_child(dialog)
|
||||||
|
elif ev is InputEventMouseMotion && (ev.button_mask & 1) != 0:
|
||||||
|
rect_position.x += ev.relative.x
|
||||||
|
rect_position.x = min(max(0, rect_position.x), get_parent().rect_size.x-rect_size.x)
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 14 KiB |
Loading…
Reference in New Issue
Block a user