1
0
Fork 0
mirror of https://github.com/Orama-Interactive/Pixelorama.git synced 2025-01-18 17:19:50 +00:00

Shader-based gradients (#677)

* Add 6 shader-based gradient types

* Shaders now respect selection

* Fix step gradient

* Remove comments

* Disable step and dithering shaders in Web version

* Fixed a weird bug with dithering shaders, selection and GLES2

Having a selection, applying a dithering gradient, removing the selection and then going to the gradient dialog again causes the dithering shaders to "remember" the previous selection, even if there is no selection currently. This only happens with the two dithering shaders and only with the GLES2 renderer. Removing `uniform sampler2D dither_texture;` from the shader code seems to fix the issue, but that's obviously isn't what we want so a "proper" fix is included in this commit.

* Format & lint

* Removed old gradient code

* Change how centers work on radial step and dithering

* Made angle, center and radius option a bit more clear

* Rename bayer-matrices directory to dither-matrices

* Use DitherMatrix class

* Create dithering types programmatically

* Remove unneeded code in shaders

* Rewrite the step shader without a for loop

More optimized and works on the Web version with GLES2

* Rewrite radial step and dithering shaders without for loop

Now all shaders work on the Web version and have been optimized.

* Fix Linear & Radial size range and remove some unneeded lines

* Added size uniform to Radial Step and Radial Dither

* Swap colors in the Linear gradient

* Make size a percentage

* Make the preview look the same as the result

Didn't change the dithering shaders because they seemed to give different results.

* Remove ratio uniform and divide uvs by the radius instead

This makes more sense because the smaller the number, the smaller the radius.

* Fix linear gradient

* Change Position to percentage and "Size" to "Transition size"

* Mix gradients with original color, if the gradient colors have transparency
This commit is contained in:
Emmanouil Papadeas 2022-05-02 16:12:00 +03:00 committed by GitHub
parent 539ccb2e58
commit cf926942ac
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 683 additions and 137 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bayer16.png-48f80e5e8f0bdac9e83b3acfa8588cf2.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/dither-matrices/bayer16.png"
dest_files=[ "res://.import/bayer16.png-48f80e5e8f0bdac9e83b3acfa8588cf2.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=1
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bayer2.png-c060ec2442edc204b9ec0ab2d99e19bf.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/dither-matrices/bayer2.png"
dest_files=[ "res://.import/bayer2.png-c060ec2442edc204b9ec0ab2d99e19bf.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=1
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bayer4.png-2008f73a4dd6b2f9f4ba6aac825a7b9b.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/dither-matrices/bayer4.png"
dest_files=[ "res://.import/bayer4.png-2008f73a4dd6b2f9f4ba6aac825a7b9b.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=1
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

View file

@ -0,0 +1,35 @@
[remap]
importer="texture"
type="StreamTexture"
path="res://.import/bayer8.png-2c0f9ff189b3d219f822ce84a94f5abd.stex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://assets/dither-matrices/bayer8.png"
dest_files=[ "res://.import/bayer8.png-2c0f9ff189b3d219f822ce84a94f5abd.stex" ]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_mode=0
compress/bptc_ldr=0
compress/normal_map=0
flags/repeat=1
flags/filter=false
flags/mipmaps=false
flags/anisotropic=false
flags/srgb=2
process/fix_alpha_border=true
process/premult_alpha=false
process/HDR_as_SRGB=false
process/invert_color=false
process/normal_map_invert_y=false
stream=false
size_limit=0
detect_3d=false
svg/scale=1.0

View file

@ -650,60 +650,3 @@ func generate_outline(
image.unlock() image.unlock()
new_image.unlock() new_image.unlock()
image.copy_from(new_image) image.copy_from(new_image)
func generate_gradient(
image: Image,
colors: Array,
steps: int,
direction: int,
affect_selection: bool,
project: Project
) -> void:
if colors.size() < 2:
return
var t = 1.0 / (steps - 1)
for i in range(1, steps - 1):
var color: Color
color = colors[-1].linear_interpolate(colors[0], t * i)
colors.insert(1, color)
if direction == GradientDirection.BOTTOM or direction == GradientDirection.RIGHT:
colors.invert()
var draw_rectangle := Rect2()
var selection := affect_selection and project.has_selection
if selection:
draw_rectangle = project.get_selection_rectangle()
else:
draw_rectangle = Rect2(Vector2.ZERO, project.size)
var size := draw_rectangle.size
image.lock()
var gradient_size
if direction == GradientDirection.TOP or direction == GradientDirection.BOTTOM:
gradient_size = size.y / steps
for i in steps:
for xx in size.x:
var start = i * gradient_size
var end = (i + 1) * gradient_size
for yy in range(start, end):
var pos: Vector2 = Vector2(xx, yy) + draw_rectangle.position
if selection and !project.selection_bitmap.get_bit(pos):
continue
image.set_pixelv(pos, colors[i])
else:
gradient_size = size.x / steps
for i in steps:
for yy in size.y:
var start = i * gradient_size
var end = (i + 1) * gradient_size
for xx in range(start, end):
var pos: Vector2 = Vector2(xx, yy) + draw_rectangle.position
if selection and !project.selection_bitmap.get_bit(pos):
continue
image.set_pixelv(pos, colors[i])
image.unlock()

View file

@ -0,0 +1,38 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D dither_texture;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec2 image_size = vec2(64.0);
uniform float position : hint_range(-0.5, 0.5) = 0.0;
uniform float size : hint_range(0.01, 2.0) = 1.0;
uniform float angle : hint_range(0.0, 360.0) = 0.0;
uniform int dither_steps : hint_range(2, 257) = 5;
uniform int pixel_size : hint_range(2, 16) = 2;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
float pivot = position / size;
vec2 uv = UV - 0.5;
float angle_cos = cos(radians(angle));
float angle_sin = sin(radians(angle));
float rotated = uv.x * angle_cos - uv.y * angle_sin;
rotated /= abs(angle_cos) + abs(angle_sin);
rotated /= size;
rotated -= pivot - 0.5;
vec4 dither_value = texture(dither_texture, uv * (image_size / float(pixel_size)));
float step_v = 1.0 / float(dither_steps);
float step_v_m = 1.0 / float(dither_steps - 1);
float rotated_stepped = floor(rotated / step_v) * step_v_m; // Similar to GDScript's stepify
float dithered = step(rotated_stepped, dither_value.r);
vec4 output = first_color * dithered + second_color * (1.0 - dithered);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -0,0 +1,26 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float position : hint_range(-0.5, 0.5) = 0.0;
uniform float size : hint_range(0.01, 2.0) = 1.0;
uniform float angle : hint_range(0.0, 360.0) = 0.0;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
uv -= 0.5;
float rotated = uv.x * cos(radians(angle)) - uv.y * sin(radians(angle));
float fixed_position = position - 0.5;
float fixed_size = (size / 2.0) + 0.5;
float pos = smoothstep((1.0 - fixed_size) + fixed_position, fixed_size + fixed_position, rotated);
vec4 output = mix(first_color, second_color, pos);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -0,0 +1,23 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec2 center = vec2(0.5);
uniform vec2 radius = vec2(1.0);
uniform float size : hint_range(0.01, 2.0) = 1.0;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
uv /= radius;
float fixed_size = (size / 2.0) + 0.5;
float smooth_dist = smoothstep(1.0 - fixed_size, fixed_size, distance(uv, center / radius));
vec4 output = second_color * smooth_dist + (1.0 - smooth_dist) * first_color;
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -0,0 +1,39 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D dither_texture;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec2 image_size = vec2(64.0);
uniform vec2 center = vec2(0.5);
uniform vec2 radius = vec2(1.0);
uniform float size : hint_range(0.01, 2) = 1.0;
uniform int dither_steps : hint_range(2, 100) = 5;
uniform int pixel_size : hint_range(2, 16) = 2;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec2 uv = UV * 2.0 - 1.0;
uv -= (center * 2.0) - vec2(1.0);
uv /= radius;
vec4 dither_value = texture(dither_texture, UV * (image_size / float(pixel_size)));
float polar_uv = length(uv);
float step_v = 1.0 / float(dither_steps);
float step_v_m = 1.0 / float(dither_steps - 1);
float uv_stepped = floor(polar_uv / step_v) * step_v_m; // Similar to GDScript's stepify
if (uv_stepped > 0.0) {
// Size should not affect the center, only the steps
polar_uv /= size;
uv_stepped = floor(polar_uv / step_v) * step_v_m;
uv_stepped += step_v_m * step(1.0, (1.0 - uv_stepped));
}
float dithered = step(uv_stepped, dither_value.r);
vec4 output = first_color * dithered + second_color * (1.0 - dithered);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -0,0 +1,36 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform vec2 center = vec2(0.5);
uniform vec2 radius = vec2(1.0);
uniform float size : hint_range(0.01, 2) = 1.0;
uniform int steps : hint_range(2, 257) = 2;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
uv = uv * 2.0 - 1.0;
uv -= (center * 2.0) - vec2(1.0);
uv /= radius;
float polar_uv = length(uv);
float step_v = 1.0 / float(steps);
float step_v_m = 1.0 / float(steps - 1);
float uv_stepped = floor(polar_uv / step_v) * step_v_m; // Similar to GDScript's stepify
if (uv_stepped > 0.0) {
// Size should not affect the center, only the steps
polar_uv /= size;
uv_stepped = floor(polar_uv / step_v) * step_v_m;
uv_stepped += step_v_m * step(1.0, (1.0 - uv_stepped));
}
uv_stepped = clamp(uv_stepped, 0.0, 1.0);
vec4 output = mix(first_color, second_color, uv_stepped);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -0,0 +1,35 @@
shader_type canvas_item;
render_mode unshaded;
uniform sampler2D selection;
uniform vec4 first_color : hint_color = vec4(1.0);
uniform vec4 second_color : hint_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float position : hint_range(-0.5, 0.5) = 0.0;
uniform float size : hint_range(0.01, 2.0) = 1.0;
uniform float angle : hint_range(0.0, 360.0) = 0.0;
uniform int steps : hint_range(2, 100) = 2;
void fragment() {
vec4 original_color = texture(TEXTURE, UV);
vec4 selection_color = texture(selection, UV);
float pivot = position / size;
vec2 tex_size = 1.0 / TEXTURE_PIXEL_SIZE;
vec2 uv = floor(UV * tex_size) / (tex_size - 1.0);
uv -= 0.5;
float angle_cos = cos(radians(angle));
float angle_sin = sin(radians(angle));
float rotated = uv.x * angle_cos - uv.y * angle_sin;
rotated /= abs(angle_cos) + abs(angle_sin);
rotated /= size;
rotated -= pivot - 0.5;
float step_v = 1.0 / float(steps);
float step_v_m = 1.0 / float(steps - 1);
float rotated_stepped = floor(rotated / step_v) * step_v_m; // Similar to GDScript's stepify
rotated_stepped = clamp(rotated_stepped, 0.0, 1.0);
vec4 output = mix(first_color, second_color, rotated_stepped);
output = mix(original_color, output, output.a);
COLOR = mix(original_color, output, selection_color.a);
}

View file

@ -1,17 +1,69 @@
extends ImageEffect extends ImageEffect
onready var options_cont = $VBoxContainer/OptionsContainer enum { LINEAR, RADIAL, STEP, RADIAL_STEP, DITHERING, RADIAL_DITHERING }
var shader_linear: Shader = preload("res://src/Shaders/Gradients/Linear.gdshader")
var shader_radial: Shader = preload("res://src/Shaders/Gradients/Radial.gdshader")
var shader_step: Shader = preload("res://src/Shaders/Gradients/Step.gdshader")
var shader_radial_step: Shader = preload("res://src/Shaders/Gradients/RadialStep.gdshader")
var shader_dither: Shader = preload("res://src/Shaders/Gradients/Dithering.gdshader")
var shader_radial_dither: Shader = preload("res://src/Shaders/Gradients/RadialDithering.gdshader")
var confirmed := false
var shader: Shader = shader_linear
var dither_matrices := [
DitherMatrix.new(preload("res://assets/dither-matrices/bayer2.png"), "Bayer 2x2"),
DitherMatrix.new(preload("res://assets/dither-matrices/bayer4.png"), "Bayer 4x4", 16),
DitherMatrix.new(preload("res://assets/dither-matrices/bayer8.png"), "Bayer 8x8", 64),
DitherMatrix.new(preload("res://assets/dither-matrices/bayer16.png"), "Bayer 16x16", 256),
]
var selected_dither_matrix: DitherMatrix = dither_matrices[0]
onready var options_cont: Container = $VBoxContainer/OptionsContainer
onready var type_option_button: OptionButton = options_cont.get_node("TypeOptionButton")
onready var color1: ColorPickerButton = options_cont.get_node("ColorsContainer/ColorPickerButton") onready var color1: ColorPickerButton = options_cont.get_node("ColorsContainer/ColorPickerButton")
onready var color2: ColorPickerButton = options_cont.get_node("ColorsContainer/ColorPickerButton2") onready var color2: ColorPickerButton = options_cont.get_node("ColorsContainer/ColorPickerButton2")
onready var position: SpinBox = options_cont.get_node("PositionSpinBox")
onready var angle: SpinBox = options_cont.get_node("AngleSpinBox")
onready var center_x: SpinBox = options_cont.get_node("CenterContainer/CenterXSpinBox")
onready var center_y: SpinBox = options_cont.get_node("CenterContainer/CenterYSpinBox")
onready var radius_x: SpinBox = options_cont.get_node("RadiusContainer/RadiusXSpinBox")
onready var radius_y: SpinBox = options_cont.get_node("RadiusContainer/RadiusYSpinBox")
onready var size: SpinBox = options_cont.get_node("SizeSpinBox")
onready var steps: SpinBox = options_cont.get_node("StepSpinBox") onready var steps: SpinBox = options_cont.get_node("StepSpinBox")
onready var direction: OptionButton = options_cont.get_node("DirectionOptionButton") onready var dithering_option_button: OptionButton = options_cont.get_node("DitheringOptionButton")
class DitherMatrix:
var texture: Texture
var name: String
var n_of_colors: int
func _init(_texture: Texture, _name: String, _n_of_colors := 4) -> void:
texture = _texture
name = _name
n_of_colors = _n_of_colors
func _ready() -> void: func _ready() -> void:
color1.get_picker().presets_visible = false color1.get_picker().presets_visible = false
color1.get_picker().deferred_mode = true
color2.get_picker().presets_visible = false color2.get_picker().presets_visible = false
color2.get_picker().deferred_mode = true var sm := ShaderMaterial.new()
sm.shader = shader
preview.set_material(sm)
for matrix in dither_matrices:
dithering_option_button.add_item(matrix.name)
func _about_to_show() -> void:
confirmed = false
._about_to_show()
func _confirmed() -> void:
confirmed = true
._confirmed()
func set_nodes() -> void: func set_nodes() -> void:
@ -20,28 +72,80 @@ func set_nodes() -> void:
affect_option_button = $VBoxContainer/OptionsContainer/AffectOptionButton affect_option_button = $VBoxContainer/OptionsContainer/AffectOptionButton
func commit_action(_cel: Image, _project: Project = Global.current_project) -> void: func commit_action(cel: Image, project: Project = Global.current_project) -> void:
DrawingAlgos.generate_gradient( var selection: Image
_cel, var selection_tex := ImageTexture.new()
[color1.color, color2.color], if selection_checkbox.pressed and project.has_selection:
steps.value, selection = project.bitmap_to_image(project.selection_bitmap)
direction.selected, else: # This is needed to prevent a weird bug with the dithering shaders and GLES2
selection_checkbox.pressed, selection = Image.new()
_project selection.create(project.size.x, project.size.y, false, Image.FORMAT_L8)
) selection_tex.create_from_image(selection, 0)
var dither_texture: Texture = selected_dither_matrix.texture
var dither_steps: int = selected_dither_matrix.n_of_colors + 1
var pixel_size: int = dither_texture.get_width()
var params := {
"first_color": color1.color,
"second_color": color2.color,
"selection": selection_tex,
"position": (position.value / 100.0) - 0.5,
"angle": angle.value,
"center": Vector2(center_x.value / 100.0, center_y.value / 100.0),
"radius": Vector2(radius_x.value, radius_y.value),
"size": size.value / 100.0,
"steps": steps.value,
"dither_texture": dither_texture,
"image_size": project.size,
"dither_steps": dither_steps,
"pixel_size": pixel_size,
}
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_ColorPickerButton_color_changed(_color: Color) -> void: func _on_TypeOptionButton_item_selected(index: int) -> void:
for child in options_cont.get_children():
if not child.is_in_group("gradient_common"):
child.visible = false
match index:
LINEAR:
shader = shader_linear
get_tree().set_group("gradient_linear", "visible", true)
RADIAL:
shader = shader_radial
get_tree().set_group("gradient_radial", "visible", true)
STEP:
shader = shader_step
get_tree().set_group("gradient_step", "visible", true)
RADIAL_STEP:
shader = shader_radial_step
get_tree().set_group("gradient_radial_step", "visible", true)
DITHERING:
shader = shader_dither
get_tree().set_group("gradient_dithering", "visible", true)
RADIAL_DITHERING:
shader = shader_radial_dither
get_tree().set_group("gradient_radial_dithering", "visible", true)
update_preview() update_preview()
func _on_ColorPickerButton2_color_changed(_color: Color) -> void: func _color_changed(_color: Color) -> void:
update_preview() update_preview()
func _on_StepSpinBox_value_changed(_value: int) -> void: func _value_changed(_value: float) -> void:
update_preview() update_preview()
func _on_DirectionOptionButton_item_selected(_index: int) -> void: func _on_DitheringOptionButton_item_selected(index: int) -> void:
selected_dither_matrix = dither_matrices[index]
update_preview() update_preview()

View file

@ -4,9 +4,9 @@
[ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2] [ext_resource path="res://src/UI/TransparentChecker.tscn" type="PackedScene" id=2]
[node name="GradientDialog" type="ConfirmationDialog"] [node name="GradientDialog" type="ConfirmationDialog"]
margin_right = 200.0 margin_right = 334.0
margin_bottom = 196.0 margin_bottom = 444.0
rect_min_size = Vector2( 172, 60.2 ) rect_min_size = Vector2( 334, 444 )
window_title = "Gradient" window_title = "Gradient"
resizable = true resizable = true
script = ExtResource( 1 ) script = ExtResource( 1 )
@ -26,14 +26,14 @@ __meta__ = {
} }
[node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"] [node name="AspectRatioContainer" type="AspectRatioContainer" parent="VBoxContainer"]
margin_right = 285.0 margin_right = 318.0
margin_bottom = 200.0 margin_bottom = 240.0
size_flags_vertical = 3 size_flags_vertical = 3
[node name="Preview" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"] [node name="Preview" type="TextureRect" parent="VBoxContainer/AspectRatioContainer"]
margin_left = 42.5 margin_left = 39.0
margin_right = 242.5 margin_right = 279.0
margin_bottom = 200.0 margin_bottom = 240.0
rect_min_size = Vector2( 200, 200 ) rect_min_size = Vector2( 200, 200 )
size_flags_horizontal = 5 size_flags_horizontal = 5
size_flags_vertical = 3 size_flags_vertical = 3
@ -48,86 +48,248 @@ margin_right = 0.0
margin_bottom = 0.0 margin_bottom = 0.0
[node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"] [node name="OptionsContainer" type="GridContainer" parent="VBoxContainer"]
margin_top = 204.0 margin_top = 244.0
margin_right = 285.0 margin_right = 318.0
margin_bottom = 304.0 margin_bottom = 400.0
columns = 2 columns = 2
[node name="Label" type="Label" parent="VBoxContainer/OptionsContainer"] [node name="TypeLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_top = 3.0 margin_top = 3.0
margin_right = 160.0 margin_right = 160.0
margin_bottom = 17.0 margin_bottom = 17.0
text = "Type:"
[node name="TypeOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_left = 164.0
margin_right = 278.0
margin_bottom = 20.0
mouse_default_cursor_shape = 2
text = "Linear"
items = [ "Linear", null, false, 0, null, "Radial", null, false, 1, null, "Step", null, false, 2, null, "Radial Step", null, false, 3, null, "Dithering", null, false, 4, null, "Radial Dithering", null, false, 5, null ]
selected = 0
[node name="ColorsLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_top = 27.0
margin_right = 160.0
margin_bottom = 41.0
text = "Colors:" text = "Colors:"
[node name="ColorsContainer" type="HBoxContainer" parent="VBoxContainer/OptionsContainer"] [node name="ColorsContainer" type="HBoxContainer" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_left = 164.0
margin_right = 285.0
margin_bottom = 20.0
[node name="ColorPickerButton" type="ColorPickerButton" parent="VBoxContainer/OptionsContainer/ColorsContainer"]
margin_right = 20.0
margin_bottom = 20.0
rect_min_size = Vector2( 20, 0 )
mouse_default_cursor_shape = 2
[node name="ColorPickerButton2" type="ColorPickerButton" parent="VBoxContainer/OptionsContainer/ColorsContainer"]
margin_left = 24.0
margin_right = 44.0
margin_bottom = 20.0
rect_min_size = Vector2( 20, 0 )
mouse_default_cursor_shape = 2
color = Color( 1, 1, 1, 1 )
[node name="Label2" type="Label" parent="VBoxContainer/OptionsContainer"]
margin_top = 29.0
margin_right = 160.0
margin_bottom = 43.0
text = "Steps:"
[node name="StepSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer"]
margin_left = 164.0 margin_left = 164.0
margin_top = 24.0 margin_top = 24.0
margin_right = 285.0 margin_right = 278.0
margin_bottom = 48.0 margin_bottom = 44.0
[node name="ColorPickerButton" type="ColorPickerButton" parent="VBoxContainer/OptionsContainer/ColorsContainer"]
margin_right = 55.0
margin_bottom = 20.0
rect_min_size = Vector2( 20, 0 )
mouse_default_cursor_shape = 2
size_flags_horizontal = 3
[node name="ColorPickerButton2" type="ColorPickerButton" parent="VBoxContainer/OptionsContainer/ColorsContainer"]
margin_left = 59.0
margin_right = 114.0
margin_bottom = 20.0
rect_min_size = Vector2( 20, 0 )
mouse_default_cursor_shape = 2
size_flags_horizontal = 3
color = Color( 1, 1, 1, 1 )
[node name="PositionLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_linear", "gradient_step"]]
margin_top = 53.0
margin_right = 160.0
margin_bottom = 67.0
text = "Position:"
[node name="PositionSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_linear", "gradient_step"]]
margin_left = 164.0
margin_top = 48.0
margin_right = 278.0
margin_bottom = 72.0
mouse_default_cursor_shape = 2
value = 50.0
suffix = "%"
[node name="AngleLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_linear", "gradient_step"]]
margin_top = 81.0
margin_right = 160.0
margin_bottom = 95.0
text = "Angle:"
[node name="AngleSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_linear", "gradient_step"]]
margin_left = 164.0
margin_top = 76.0
margin_right = 278.0
margin_bottom = 100.0
mouse_default_cursor_shape = 2
max_value = 360.0
suffix = "°"
[node name="SizeLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_top = 109.0
margin_right = 160.0
margin_bottom = 123.0
text = "Transition size:"
[node name="SizeSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_left = 164.0
margin_top = 104.0
margin_right = 278.0
margin_bottom = 128.0
mouse_default_cursor_shape = 2
min_value = 1.0
max_value = 200.0
value = 100.0
suffix = "%"
[node name="StepsLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial_step", "gradient_step"]]
visible = false
margin_top = 137.0
margin_right = 160.0
margin_bottom = 151.0
text = "Steps:"
[node name="StepSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial_step", "gradient_step"]]
visible = false
margin_left = 164.0
margin_top = 132.0
margin_right = 316.0
margin_bottom = 156.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
min_value = 2.0 min_value = 2.0
value = 2.0 value = 2.0
[node name="Label3" type="Label" parent="VBoxContainer/OptionsContainer"] [node name="CenterLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial", "gradient_radial_dithering", "gradient_radial_step"]]
margin_top = 55.0 visible = false
margin_top = 165.0
margin_right = 160.0 margin_right = 160.0
margin_bottom = 69.0 margin_bottom = 179.0
text = "Direction:" text = "Center:"
[node name="DirectionOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer"] [node name="CenterContainer" type="HBoxContainer" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial", "gradient_radial_dithering", "gradient_radial_step"]]
margin_left = 164.0 visible = false
margin_top = 52.0 margin_top = 132.0
margin_right = 285.0 margin_right = 183.0
margin_bottom = 72.0 margin_bottom = 156.0
[node name="XLabel" type="Label" parent="VBoxContainer/OptionsContainer/CenterContainer"]
margin_top = 5.0
margin_right = 12.0
margin_bottom = 19.0
text = "X:"
[node name="CenterXSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer/CenterContainer"]
margin_left = 16.0
margin_right = 90.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
text = "Top to Bottom" value = 50.0
items = [ "Top to Bottom", null, false, 0, null, "Bottom to Top", null, false, 1, null, "Left to Right", null, false, 2, null, "Right to Left", null, false, 3, null ] suffix = "%"
selected = 0
[node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer"] [node name="YLabel" type="Label" parent="VBoxContainer/OptionsContainer/CenterContainer"]
margin_top = 76.0 margin_left = 94.0
margin_top = 5.0
margin_right = 105.0
margin_bottom = 19.0
text = "Y:"
[node name="CenterYSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer/CenterContainer"]
margin_left = 109.0
margin_right = 183.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
value = 50.0
suffix = "%"
[node name="RadiusLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial", "gradient_radial_dithering", "gradient_radial_step"]]
visible = false
margin_top = 193.0
margin_right = 160.0 margin_right = 160.0
margin_bottom = 100.0 margin_bottom = 207.0
text = "Radius:"
[node name="RadiusContainer" type="HBoxContainer" parent="VBoxContainer/OptionsContainer" groups=["gradient_radial", "gradient_radial_dithering", "gradient_radial_step"]]
visible = false
margin_left = 164.0
margin_top = 188.0
margin_right = 316.0
margin_bottom = 212.0
[node name="XLabel" type="Label" parent="VBoxContainer/OptionsContainer/RadiusContainer"]
margin_left = -164.0
margin_top = -51.0
margin_right = -152.0
margin_bottom = -37.0
text = "X:"
[node name="RadiusXSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer/RadiusContainer"]
margin_right = 74.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
min_value = 0.01
step = 0.01
value = 1.0
[node name="YLabel" type="Label" parent="VBoxContainer/OptionsContainer/RadiusContainer"]
margin_left = -70.0
margin_top = -51.0
margin_right = -59.0
margin_bottom = -37.0
text = "Y:"
[node name="RadiusYSpinBox" type="SpinBox" parent="VBoxContainer/OptionsContainer/RadiusContainer"]
margin_left = 78.0
margin_right = 152.0
margin_bottom = 24.0
mouse_default_cursor_shape = 2
min_value = 0.01
step = 0.01
value = 1.0
[node name="DitheringLabel" type="Label" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_radial_dithering"]]
visible = false
margin_top = 219.0
margin_right = 160.0
margin_bottom = 233.0
text = "Dithering pattern:"
[node name="DitheringOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer" groups=["gradient_dithering", "gradient_radial_dithering"]]
visible = false
margin_left = 164.0
margin_top = 216.0
margin_right = 316.0
margin_bottom = 236.0
mouse_default_cursor_shape = 2
text = "Bayer 2x2"
[node name="SelectionCheckBox" type="CheckBox" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_top = 132.0
margin_right = 160.0
margin_bottom = 156.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
pressed = true pressed = true
text = "Only affect selection" text = "Only affect selection"
[node name="AffectOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer"] [node name="AffectOptionButton" type="OptionButton" parent="VBoxContainer/OptionsContainer" groups=["gradient_common"]]
margin_left = 164.0 margin_left = 164.0
margin_top = 76.0 margin_top = 132.0
margin_right = 285.0 margin_right = 278.0
margin_bottom = 100.0 margin_bottom = 156.0
mouse_default_cursor_shape = 2 mouse_default_cursor_shape = 2
text = "Selected cels" 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 ] 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 selected = 0
[connection signal="color_changed" from="VBoxContainer/OptionsContainer/ColorsContainer/ColorPickerButton" to="." method="_on_ColorPickerButton_color_changed"] [connection signal="item_selected" from="VBoxContainer/OptionsContainer/TypeOptionButton" to="." method="_on_TypeOptionButton_item_selected"]
[connection signal="color_changed" from="VBoxContainer/OptionsContainer/ColorsContainer/ColorPickerButton2" to="." method="_on_ColorPickerButton2_color_changed"] [connection signal="color_changed" from="VBoxContainer/OptionsContainer/ColorsContainer/ColorPickerButton" to="." method="_color_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/StepSpinBox" to="." method="_on_StepSpinBox_value_changed"] [connection signal="color_changed" from="VBoxContainer/OptionsContainer/ColorsContainer/ColorPickerButton2" to="." method="_color_changed"]
[connection signal="item_selected" from="VBoxContainer/OptionsContainer/DirectionOptionButton" to="." method="_on_DirectionOptionButton_item_selected"] [connection signal="value_changed" from="VBoxContainer/OptionsContainer/PositionSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/AngleSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/SizeSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/StepSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/CenterContainer/CenterXSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/CenterContainer/CenterYSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/RadiusContainer/RadiusXSpinBox" to="." method="_value_changed"]
[connection signal="value_changed" from="VBoxContainer/OptionsContainer/RadiusContainer/RadiusYSpinBox" to="." method="_value_changed"]
[connection signal="item_selected" from="VBoxContainer/OptionsContainer/DitheringOptionButton" to="." method="_on_DitheringOptionButton_item_selected"]