Added the color picker, the float edit, and the gradient editor widgets from material maker.

This commit is contained in:
Relintai 2021-10-17 00:11:51 +02:00
parent 7ab05bf407
commit 45fc6bcdbd
8 changed files with 544 additions and 0 deletions

View File

@ -0,0 +1,15 @@
extends ColorPickerButton
func get_drag_data(_position):
var preview = ColorRect.new()
preview.color = color
preview.rect_min_size = Vector2(32, 32)
set_drag_preview(preview)
return color
func can_drop_data(_position, data) -> bool:
return typeof(data) == TYPE_COLOR
func drop_data(_position, data) -> void:
color = data
emit_signal("color_changed", color)

View File

@ -0,0 +1,14 @@
[gd_scene format=2]
[node name="ColorPickerPopup" type="PopupPanel"]
margin_right = 316.0
margin_bottom = 466.0
[node name="ColorPicker" type="ColorPicker" parent="."]
margin_left = 4.0
margin_top = 4.0
margin_right = 312.0
margin_bottom = 466.0
__meta__ = {
"_edit_use_anchors_": false
}

View File

@ -0,0 +1,138 @@
extends LineEdit
export var value : float = 0.5 setget set_value
export var min_value : float = 0.0 setget set_min_value
export var max_value : float = 1.0 setget set_max_value
export var step : float = 0.0 setget set_step
export var float_only : bool = false
var sliding : bool = false
var start_position : float
var last_position : float
var start_value : float
var modifiers : int
var from_lower_bound : bool = false
var from_upper_bound : bool = false
onready var slider = $Slider
onready var cursor = $Slider/Cursor
signal value_changed(value)
func _ready() -> void:
do_update()
func set_value(v) -> void:
if v is float:
value = v
do_update()
$Slider.visible = true
elif v is String and !float_only:
text = v
$Slider.visible = false
func set_min_value(v : float) -> void:
min_value = v
do_update()
func set_max_value(v : float) -> void:
max_value = v
do_update()
func set_step(v : float) -> void:
step = v
do_update()
func do_update(update_text : bool = true) -> void:
if update_text and $Slider.visible:
text = str(value)
if cursor != null:
if max_value != min_value:
cursor.rect_position.x = (clamp(value, min_value, max_value)-min_value)*(slider.rect_size.x-cursor.rect_size.x)/(max_value-min_value)
else:
cursor.rect_position.x = 0
func get_modifiers(event):
var new_modifiers = 0
if event.shift:
new_modifiers |= 1
if event.control:
new_modifiers |= 2
if event.alt:
new_modifiers |= 4
return new_modifiers
func _on_LineEdit_gui_input(event : InputEvent) -> void:
if !$Slider.visible or !editable:
return
if event is InputEventMouseButton and event.button_index == BUTTON_LEFT:
if event.is_pressed():
last_position = event.position.x
start_position = last_position
start_value = value
sliding = true
from_lower_bound = value <= min_value
from_upper_bound = value >= max_value
modifiers = get_modifiers(event)
else:
sliding = false
elif sliding and event is InputEventMouseMotion and event.button_mask == BUTTON_MASK_LEFT:
var new_modifiers = get_modifiers(event)
if new_modifiers != modifiers:
start_position = last_position
start_value = value
modifiers = new_modifiers
else:
last_position = event.position.x
var delta : float = last_position-start_position
var current_step = step
if event.control:
delta *= 0.2
elif event.shift:
delta *= 5.0
if event.alt:
current_step *= 0.01
var v : float = start_value+sign(delta)*pow(abs(delta)*0.005, 2)*abs(max_value - min_value)
if current_step != 0:
v = min_value+floor((v - min_value)/current_step)*current_step
if !from_lower_bound and v < min_value:
v = min_value
if !from_upper_bound and v > max_value:
v = max_value
set_value(v)
select(0, 0)
emit_signal("value_changed", value)
release_focus()
elif event is InputEventKey and !event.echo:
match event.scancode:
KEY_SHIFT, KEY_CONTROL, KEY_ALT:
start_position = last_position
start_value = value
modifiers = get_modifiers(event)
func _on_LineEdit_text_changed(new_text : String) -> void:
if new_text.is_valid_float():
value = new_text.to_float()
do_update(false)
func _on_LineEdit_text_entered(new_text : String, release = true) -> void:
if new_text.is_valid_float():
value = new_text.to_float()
do_update()
emit_signal("value_changed", value)
$Slider.visible = true
elif float_only:
do_update()
emit_signal("value_changed", value)
$Slider.visible = true
else:
emit_signal("value_changed", new_text)
$Slider.visible = false
if release:
release_focus()
func _on_FloatEdit_focus_entered():
select_all()
func _on_LineEdit_focus_exited() -> void:
_on_LineEdit_text_entered(text, false)

View File

@ -0,0 +1,45 @@
[gd_scene load_steps=2 format=2]
[ext_resource path="res://material_maker/widgets/float_edit/float_edit.gd" type="Script" id=1]
[node name="FloatEdit" type="LineEdit"]
anchor_left = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = -1280.0
margin_right = -1222.0
margin_bottom = -696.0
focus_mode = 1
text = "0.5"
max_length = 100
context_menu_enabled = false
caret_blink = true
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Slider" type="ColorRect" parent="."]
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 2.0
margin_top = -3.0
margin_right = -2.0
margin_bottom = -3.0
rect_min_size = Vector2( 0, 2 )
mouse_filter = 2
color = Color( 0.501961, 0.501961, 0.501961, 1 )
[node name="Cursor" type="ColorRect" parent="Slider"]
margin_right = 3.0
margin_bottom = 1.0
rect_min_size = Vector2( 3, 2 )
mouse_filter = 2
[connection signal="focus_entered" from="." to="." method="_on_FloatEdit_focus_entered"]
[connection signal="focus_exited" from="." to="." method="_on_LineEdit_focus_exited"]
[connection signal="gui_input" from="." to="." method="_on_LineEdit_gui_input"]
[connection signal="resized" from="." to="." method="do_update"]
[connection signal="text_changed" from="." to="." method="_on_LineEdit_text_changed"]
[connection signal="text_entered" from="." to="." method="_on_LineEdit_text_entered"]
[connection signal="resized" from="Slider" to="." method="do_update"]

View File

@ -0,0 +1,184 @@
extends Control
class GradientCursor:
extends Control
var color : Color
var sliding : bool = false
onready var label : Label = get_parent().get_node("Value")
const WIDTH : int = 10
func _ready() -> void:
rect_position = Vector2(0, 15)
rect_size = Vector2(WIDTH, 15)
func _draw() -> void:
# warning-ignore:integer_division
var polygon : PoolVector2Array = PoolVector2Array([Vector2(0, 5), Vector2(WIDTH/2, 0), Vector2(WIDTH, 5), Vector2(WIDTH, 15), Vector2(0, 15), Vector2(0, 5)])
var c = color
c.a = 1.0
draw_colored_polygon(polygon, c)
draw_polyline(polygon, Color(0.0, 0.0, 0.0) if color.v > 0.5 else Color(1.0, 1.0, 1.0))
func _gui_input(ev) -> void:
if ev is InputEventMouseButton:
if ev.button_index == BUTTON_LEFT:
if ev.doubleclick:
get_parent().select_color(self, ev.global_position)
elif ev.pressed:
sliding = true
label.visible = true
label.text = "%.03f" % get_cursor_position()
else:
sliding = false
label.visible = false
elif ev.button_index == BUTTON_RIGHT and get_parent().get_sorted_cursors().size() > 2:
var parent = get_parent()
parent.remove_child(self)
parent.update_value()
queue_free()
elif ev is InputEventMouseMotion and (ev.button_mask & BUTTON_MASK_LEFT) != 0 and sliding:
rect_position.x += get_local_mouse_position().x
if ev.control:
rect_position.x = round(get_cursor_position()*20.0)*0.05*(get_parent().rect_size.x - WIDTH)
rect_position.x = min(max(0, rect_position.x), get_parent().rect_size.x-rect_size.x)
get_parent().update_value()
label.text = "%.03f" % get_cursor_position()
func get_cursor_position() -> float:
return rect_position.x / (get_parent().rect_size.x - WIDTH)
func set_color(c) -> void:
color = c
get_parent().update_value()
update()
static func sort(a, b) -> bool:
return a.get_position() < b.get_position()
func can_drop_data(_position, data) -> bool:
return typeof(data) == TYPE_COLOR
func drop_data(_position, data) -> void:
set_color(data)
var value = null setget set_value
export var embedded : bool = true
signal updated(value)
func _ready() -> void:
$Gradient.material = $Gradient.material.duplicate(true)
#set_value(MMGradient.new())
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 set_value(v) -> void:
value = v
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()
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()
func add_cursor(x, color) -> void:
var cursor = GradientCursor.new()
add_child(cursor)
cursor.rect_position.x = x
cursor.color = color
func _gui_input(ev) -> void:
if ev is InputEventMouseButton and ev.button_index == 1 and ev.doubleclick:
if ev.position.y > 15:
var p = clamp(ev.position.x, 0, rect_size.x-GradientCursor.WIDTH)
add_cursor(p, get_gradient_color(p))
update_value()
elif embedded:
var popup = load("res://material_maker/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)))
popup.set_global_position(ev.global_position-Vector2(popup_size.x / 2, popup_size.y))
popup.init(value)
popup.connect("updated", self, "set_value")
popup.connect("popup_hide", popup, "queue_free")
# Showing a color picker popup to change a cursor's color
var active_cursor
func select_color(cursor, position) -> void:
active_cursor = cursor
var color_picker_popup = preload("res://addons/mat_maker_gd/widgets/color_picker_popup/color_picker_popup.tscn").instance()
add_child(color_picker_popup)
var color_picker = color_picker_popup.get_node("ColorPicker")
color_picker.color = cursor.color
color_picker.connect("color_changed", cursor, "set_color")
color_picker_popup.rect_position = position
color_picker_popup.connect("popup_hide", color_picker_popup, "queue_free")
color_picker_popup.popup()
# Calculating a color from the gradient and generating the shader
func get_sorted_cursors() -> Array:
var array = []
for c in get_children():
if c is GradientCursor:
array.append(c)
array.sort_custom(GradientCursor, "sort")
return array
func get_gradient_color(x) -> Color:
return value.get_color(x / (rect_size.x - GradientCursor.WIDTH))
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)
func _on_Interpolation_item_selected(ID) -> void:
value.interpolation = ID
update_shader()

View File

@ -0,0 +1,105 @@
[gd_scene load_steps=12 format=2]
[ext_resource path="res://material_maker/widgets/gradient_editor/gradient_editor.gd" type="Script" id=1]
[ext_resource path="res://material_maker/icons/icons.tres" type="Texture" id=2]
[sub_resource type="Shader" id=1]
code = "shader_type canvas_item;
void fragment() {
COLOR = vec4(vec3(2.0*fract(0.5*(floor(0.12*FRAGCOORD.x)+floor(0.125*FRAGCOORD.y)))), 1.0);
}"
[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 = 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
rect_min_size = Vector2( 120, 32 )
focus_mode = 1
script = ExtResource( 1 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Background" type="ColorRect" parent="."]
material = SubResource( 2 )
anchor_right = 1.0
margin_left = 4.0
margin_right = -4.0
margin_bottom = 15.0
rect_min_size = Vector2( 112, 17 )
mouse_filter = 2
[node name="Gradient" type="ColorRect" parent="."]
material = SubResource( 4 )
anchor_right = 1.0
margin_left = 4.0
margin_right = -4.0
margin_bottom = 15.0
rect_min_size = Vector2( 112, 17 )
mouse_filter = 2
theme = SubResource( 5 )
[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
[node name="Value" type="Label" parent="."]
anchor_right = 1.0
margin_top = -1.0
margin_bottom = 14.0
custom_colors/font_color = Color( 1, 1, 1, 1 )
custom_colors/font_color_shadow = Color( 0, 0, 0, 1 )
custom_constants/shadow_offset_x = 1
custom_constants/shadow_offset_y = 1
custom_constants/shadow_as_outline = 1
align = 1
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="item_selected" from="Interpolation" to="." method="_on_Interpolation_item_selected"]

View File

@ -0,0 +1,12 @@
extends Popup
signal updated(value)
func init(value) -> void:
$Panel/Control.set_value(value)
func _on_Control_updated(value) -> void:
emit_signal("updated", value)
func _on_GradientPopup_popup_hide() -> void:
queue_free()

View File

@ -0,0 +1,31 @@
[gd_scene load_steps=4 format=2]
[ext_resource path="res://material_maker/widgets/gradient_editor/gradient_popup.gd" type="Script" id=1]
[ext_resource path="res://material_maker/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 )
[node name="GradientPopup" type="Popup"]
margin_right = 632.0
margin_bottom = 49.0
size_flags_horizontal = 0
size_flags_vertical = 0
script = ExtResource( 1 )
[node name="Panel" type="Panel" parent="."]
margin_right = 632.0
margin_bottom = 49.0
custom_styles/panel = SubResource( 1 )
[node name="Control" parent="Panel" instance=ExtResource( 2 )]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
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"]