-
-
Notifications
You must be signed in to change notification settings - Fork 397
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a Gradient Map image effect, implements the second half of #595
The gradient edit code was taken and modified from Material Maker, MIT license.
- Loading branch information
1 parent
872ac62
commit c9f0301
Showing
9 changed files
with
364 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
shader_type canvas_item; | ||
|
||
uniform sampler2D map; // GradientTexture | ||
uniform sampler2D selection; | ||
|
||
void fragment() { | ||
vec4 original_color = texture(TEXTURE, UV); | ||
vec4 selection_color = texture(selection, UV); | ||
vec4 output = original_color; | ||
float value = (0.2126 * original_color.r) + (0.7152 * original_color.g) + (0.0722 * original_color.b); | ||
vec4 gradient_color = texture(map, vec2(value, 0.0)); | ||
output.rgb = gradient_color.rgb; | ||
output.a *= gradient_color.a; | ||
|
||
COLOR = mix(original_color, output, selection_color.a); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
extends ImageEffect | ||
|
||
var shader: Shader = preload("res://src/Shaders/GradientMap.gdshader") | ||
var confirmed := false | ||
|
||
|
||
# Called when the node enters the scene tree for the first time. | ||
func _ready() -> void: | ||
var sm := ShaderMaterial.new() | ||
sm.shader = shader | ||
preview.set_material(sm) | ||
|
||
|
||
func set_nodes() -> void: | ||
preview = $VBoxContainer/AspectRatioContainer/Preview | ||
selection_checkbox = $VBoxContainer/OptionsContainer/SelectionCheckBox | ||
affect_option_button = $VBoxContainer/OptionsContainer/AffectOptionButton | ||
|
||
|
||
func _about_to_show() -> void: | ||
confirmed = false | ||
._about_to_show() | ||
|
||
|
||
func _confirmed() -> void: | ||
confirmed = true | ||
._confirmed() | ||
|
||
|
||
func commit_action(cel: Image, project: Project = Global.current_project) -> void: | ||
var selection_tex := ImageTexture.new() | ||
if selection_checkbox.pressed and project.has_selection: | ||
var selection: Image = project.bitmap_to_image(project.selection_bitmap) | ||
selection_tex.create_from_image(selection, 0) | ||
|
||
var params := {"selection": selection_tex, "map": $VBoxContainer/GradientEdit.texture} | ||
|
||
if !confirmed: | ||
preview.material.shader = shader | ||
for param in params: | ||
preview.material.set_shader_param(param, params[param]) | ||
else: | ||
var gen := ShaderImageEffect.new() | ||
gen.generate_image(cel, shader, params, project.size) | ||
yield(gen, "done") | ||
|
||
|
||
func _on_GradientEdit_updated(_gradient, _cc) -> void: | ||
update_preview() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
[gd_scene load_steps=4 format=2] | ||
|
||
[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=1] | ||
[ext_resource path="res://src/UI/Nodes/GradientEdit.tscn" type="PackedScene" id=2] | ||
[ext_resource path="res://src/UI/Dialogs/ImageEffects/GradientMapDialog.gd" type="Script" id=3] | ||
|
||
[node name="GradientMapDialog" type="ConfirmationDialog"] | ||
margin_right = 200.0 | ||
margin_bottom = 70.0 | ||
window_title = "Gradient Map" | ||
resizable = true | ||
script = ExtResource( 3 ) | ||
|
||
[node name="VBoxContainer" type="VBoxContainer" parent="."] | ||
anchor_right = 1.0 | ||
anchor_bottom = 1.0 | ||
margin_left = 8.0 | ||
margin_top = 8.0 | ||
margin_right = -8.0 | ||
margin_bottom = -36.0 | ||
__meta__ = { | ||
"_edit_use_anchors_": false | ||
} | ||
|
||
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"] | ||
margin_right = 278.0 | ||
margin_bottom = 200.0 | ||
size_flags_vertical = 3 | ||
|
||
[node name="Preview" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"] | ||
margin_left = 39.0 | ||
margin_right = 239.0 | ||
margin_bottom = 200.0 | ||
rect_min_size = Vector2( 200, 200 ) | ||
size_flags_horizontal = 5 | ||
size_flags_vertical = 3 | ||
expand = true | ||
stretch_mode = 5 | ||
|
||
[node name="TransparentChecker" parent="VBoxContainer/AspectRatioContainer/Preview" instance=ExtResource( 1 )] | ||
show_behind_parent = true | ||
anchor_right = 1.0 | ||
anchor_bottom = 1.0 | ||
margin_right = 0.0 | ||
margin_bottom = 0.0 | ||
|
||
[node name="GradientEdit" parent="VBoxContainer" instance=ExtResource( 2 )] | ||
anchor_right = 0.0 | ||
anchor_bottom = 0.0 | ||
margin_top = 204.0 | ||
margin_right = 278.0 | ||
margin_bottom = 234.0 | ||
rect_min_size = Vector2( 0, 30 ) | ||
|
||
[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"] | ||
margin_top = 238.0 | ||
margin_right = 278.0 | ||
margin_bottom = 262.0 | ||
columns = 2 | ||
|
||
[node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]] | ||
margin_right = 160.0 | ||
margin_bottom = 24.0 | ||
mouse_default_cursor_shape = 2 | ||
pressed = true | ||
text = "Only affect selection" | ||
|
||
[node name="AffectOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]] | ||
margin_left = 164.0 | ||
margin_right = 278.0 | ||
margin_bottom = 24.0 | ||
mouse_default_cursor_shape = 2 | ||
text = "Selected cels" | ||
items = [ "Selected cels", null, false, 0, null, "Current frame", null, false, 1, null, "All frames", null, false, 2, null, "All projects", null, false, 3, null ] | ||
selected = 0 | ||
|
||
[connection signal="updated" from="VBoxContainer/GradientEdit" to="." method="_on_GradientEdit_updated"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
# Code taken and modified from Material Maker, licensed under MIT | ||
# gdlint: ignore=max-line-length | ||
# https://github.com/RodZill4/material-maker/blob/master/material_maker/widgets/gradient_editor/gradient_editor.gd | ||
class_name GradientEditNode | ||
extends TextureRect | ||
|
||
signal updated(gradient, cc) | ||
|
||
var continuous_change := true | ||
var active_cursor: GradientCursor # Showing a color picker popup to change a cursor's color | ||
|
||
onready var x_offset: float = rect_size.x - GradientCursor.WIDTH | ||
onready var gradient: Gradient = texture.gradient | ||
|
||
|
||
class GradientCursor: | ||
extends Control | ||
|
||
const WIDTH := 10 | ||
var color: Color | ||
var sliding := false | ||
onready var label: Label = get_parent().get_node("Value") | ||
|
||
func _ready() -> void: | ||
rect_position = Vector2(0, 15) | ||
rect_size = Vector2(WIDTH, 15) | ||
|
||
func _draw() -> void: | ||
# warning-ignore:integer_division | ||
var polygon := 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: InputEvent) -> 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: | ||
get_parent().continuous_change = false | ||
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.continuous_change = false | ||
parent.update_from_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_from_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: Color) -> void: | ||
color = c | ||
get_parent().update_from_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) | ||
|
||
|
||
func _ready() -> void: | ||
create_cursors() | ||
|
||
|
||
func create_cursors() -> void: | ||
for c in get_children(): | ||
if c is GradientCursor: | ||
remove_child(c) | ||
c.queue_free() | ||
for i in gradient.get_point_count(): | ||
var p: float = gradient.get_offset(i) | ||
add_cursor(p * x_offset, gradient.get_color(i)) | ||
|
||
|
||
func _gui_input(ev: InputEvent) -> void: | ||
if ev.is_action_pressed("left_mouse"): | ||
var p = clamp(ev.position.x, 0, x_offset) | ||
add_cursor(p, get_gradient_color(p)) | ||
continuous_change = false | ||
update_from_value() | ||
|
||
|
||
func update_from_value() -> void: | ||
gradient.offsets = [] | ||
for c in get_children(): | ||
if c is GradientCursor: | ||
var point: float = c.rect_position.x / x_offset | ||
gradient.add_point(point, c.color) | ||
emit_signal("updated", gradient, continuous_change) | ||
continuous_change = true | ||
|
||
|
||
func add_cursor(x: float, color: Color) -> void: | ||
var cursor := GradientCursor.new() | ||
add_child(cursor) | ||
cursor.rect_position.x = x | ||
cursor.color = color | ||
|
||
|
||
func select_color(cursor: GradientCursor, position: Vector2) -> void: | ||
active_cursor = cursor | ||
var color_picker = $Popup.get_node("ColorPicker") | ||
color_picker.color = cursor.color | ||
$Popup.rect_position = position | ||
$Popup.popup() | ||
|
||
|
||
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: float) -> Color: | ||
return gradient.interpolate(x / x_offset) | ||
|
||
|
||
func _on_ColorPicker_color_changed(color: Color) -> void: | ||
active_cursor.set_color(color) | ||
|
||
|
||
func _on_GradientEdit_resized() -> void: | ||
if not gradient: | ||
return | ||
x_offset = rect_size.x - GradientCursor.WIDTH | ||
create_cursors() |
Oops, something went wrong.