From 722eb59b3a0c184e004557d0049503c46c6575b0 Mon Sep 17 00:00:00 2001 From: Emmanouil Papadeas <35376950+OverloadedOrama@users.noreply.github.com> Date: Thu, 30 Jan 2025 17:05:32 +0200 Subject: [PATCH] Group all of the color channel curves of the color curves layer effect Making it consistent with its image effect counterpart. The code inside ShaderLoader.gd keeps getting uglier and uglier, it might be worth a refactor at some point. --- src/Classes/ShaderLoader.gd | 65 ++++++++++++++++++++---- src/Shaders/Effects/ColorCurves.gdshader | 3 +- src/UI/Nodes/CurveEditor/CurveEdit.gd | 14 +++-- 3 files changed, 67 insertions(+), 15 deletions(-) diff --git a/src/Classes/ShaderLoader.gd b/src/Classes/ShaderLoader.gd index 68f342967..3e0a755a3 100644 --- a/src/Classes/ShaderLoader.gd +++ b/src/Classes/ShaderLoader.gd @@ -19,6 +19,9 @@ static func create_ui_for_shader_uniforms( var uniform_data: PackedStringArray = [] var description: String = "" var description_began := false + # A Dictionary of [String] and [Control], used to group together nodes + # under the same group_uniform. Currently only used for CurveTextures. + var group_nodes := {} var color_button_hbox: HBoxContainer = null # Used for RGBA buttons, if they exist. for line in code: # Management of "end" tags @@ -28,7 +31,7 @@ static func create_ui_for_shader_uniforms( description += "\n" + line.strip_edges() # Detection of uniforms - if line.begins_with("uniform"): + if line.begins_with("uniform") or line.begins_with("group_uniforms"): uniforms.append(line) if line.begins_with("// uniform_data"): uniform_data.append(line) @@ -45,6 +48,7 @@ static func create_ui_for_shader_uniforms( "Description:\n", description.replace("//", "").strip_edges() ) + var current_group := "" for uniform in uniforms: # Example uniform: # uniform float parameter_name : hint_range(0, 255) = 100.0; @@ -62,6 +66,10 @@ static func create_ui_for_shader_uniforms( u_hint = u_hint.replace(";", "") var u_init := u_left_side[0].split(" ") + var uniform_string := u_init[0] + if uniform_string == "group_uniforms": + current_group = u_init[1] + continue var u_type := u_init[1] var u_name := u_init[2] if u_name in ["PXO_time", "PXO_frame_index", "PXO_layer_index"]: @@ -237,11 +245,13 @@ static func create_ui_for_shader_uniforms( func(): _shader_update_palette_texture(palette, value_changed, u_name) ) continue - var label := Label.new() - label.text = humanized_u_name - label.size_flags_horizontal = Control.SIZE_EXPAND_FILL var hbox := HBoxContainer.new() - hbox.add_child(label) + if not (u_name.begins_with("curve_") and not current_group.is_empty()): + var label := Label.new() + label.text = humanized_u_name + label.size_flags_horizontal = Control.SIZE_EXPAND_FILL + hbox.add_child(label) + parent_node.add_child(hbox) if shader is VisualShader and u_name.begins_with("tex_frg_"): var node_id := int(u_name.replace("tex_frg_", "")) var shader_node := (shader as VisualShader).get_node( @@ -263,14 +273,50 @@ static func create_ui_for_shader_uniforms( elif u_name.begins_with("gradient_"): _create_gradient_texture_ui(params, u_name, hbox, value_changed) elif u_name.begins_with("curve_"): - _create_curve_texture_ui(params, u_name, hbox, value_changed) + if current_group.is_empty(): + _create_curve_texture_ui(params, u_name, hbox, value_changed) + else: + # If this curve uniform belongs in a group, group them into the same + # CurveEdit node and use an OptionButton to switch between the different curves. + var group_option_button_str := current_group + "_option_button" + if group_nodes.has(group_option_button_str): + # Add it to the current group CurveEdit and OptionButton. + var option_button := group_nodes[group_option_button_str] as OptionButton + if not params.has(u_name): + var new_curve := Curve.new() + # Set linear preset to the new curve + CurveEdit.set_curve_preset(new_curve, 0) + params[u_name] = CurveEdit.to_texture(new_curve) + option_button.add_item(Keychain.humanize_snake_case(u_name.replace("curve_", ""))) + option_button.set_item_metadata(option_button.item_count - 1, u_name) + else: # Create a the group's CurveEdit and OptionButton. + var option_button := OptionButton.new() + parent_node.add_child(option_button) + var curve_edit := _create_curve_texture_ui(params, u_name, parent_node, value_changed) + option_button.add_item(Keychain.humanize_snake_case(u_name.replace("curve_", ""))) + option_button.set_item_metadata(option_button.item_count - 1, u_name) + option_button.size_flags_horizontal = Control.SIZE_EXPAND_FILL + option_button.mouse_default_cursor_shape = Control.CURSOR_POINTING_HAND + option_button.item_selected.connect( + # Disconnect all previous connections from the + # curve_edit's value_changed signal. Then change the curve, and then + # connect a new callable to the value_changed signal. + func(index: int): + var new_uniform_name = option_button.get_item_metadata(index) + for connection in curve_edit.value_changed.get_connections(): + curve_edit.value_changed.disconnect(connection.callable) + curve_edit.curve = params[new_uniform_name].curve + curve_edit.value_changed.connect( + func(curve: Curve): value_changed.call(CurveEdit.to_texture(curve), new_uniform_name) + ) + ) + group_nodes[group_option_button_str] = option_button elif u_name.begins_with("noise_"): _create_noise_texture_ui(params, u_name, hbox, value_changed, parent_node) else: # Simple texture _create_simple_texture_ui( params, u_name, hbox, value_changed, parent_node, file_selected ) - parent_node.add_child(hbox) elif u_type == "bool": var button: BaseButton if u_name in ["red", "green", "blue", "alpha"]: @@ -436,8 +482,8 @@ static func _create_gradient_texture_ui( static func _create_curve_texture_ui( - params: Dictionary, u_name: String, hbox: BoxContainer, value_changed: Callable -) -> void: + params: Dictionary, u_name: String, hbox: Control, value_changed: Callable +) -> CurveEdit: var curve_edit := CurveEdit.new() curve_edit.size_flags_horizontal = Control.SIZE_EXPAND_FILL if params.has(u_name) and params[u_name] is CurveTexture: @@ -449,6 +495,7 @@ static func _create_curve_texture_ui( func(curve: Curve): value_changed.call(CurveEdit.to_texture(curve), u_name) ) hbox.add_child(curve_edit) + return curve_edit static func _create_noise_texture_ui( diff --git a/src/Shaders/Effects/ColorCurves.gdshader b/src/Shaders/Effects/ColorCurves.gdshader index bd36d04c6..6d5e6ba1a 100644 --- a/src/Shaders/Effects/ColorCurves.gdshader +++ b/src/Shaders/Effects/ColorCurves.gdshader @@ -1,6 +1,8 @@ shader_type canvas_item; +uniform sampler2D selection : filter_nearest; // CurveTexture(s) +group_uniforms channel; uniform sampler2D curve_rgb; uniform sampler2D curve_red; uniform sampler2D curve_green; @@ -9,7 +11,6 @@ uniform sampler2D curve_alpha; uniform sampler2D curve_hue; uniform sampler2D curve_sat; uniform sampler2D curve_value; -uniform sampler2D selection : filter_nearest; vec3 rgb2hsb(vec3 c) { diff --git a/src/UI/Nodes/CurveEditor/CurveEdit.gd b/src/UI/Nodes/CurveEditor/CurveEdit.gd index 1a4571f8e..305d1d182 100644 --- a/src/UI/Nodes/CurveEditor/CurveEdit.gd +++ b/src/UI/Nodes/CurveEditor/CurveEdit.gd @@ -18,7 +18,7 @@ signal value_changed(value: Curve) update_controls() ## Array of dictionaries of key [String] and value [Array] of type [CurveEdit.CurvePoint]. -var presets: Array[Dictionary] = [ +static var presets: Array[Dictionary] = [ {"Linear": [CurvePoint.new(0.0, 0.0, 0.0, 1.0), CurvePoint.new(1.0, 1.0, 1.0, 0.0)]}, { "Ease out": @@ -154,6 +154,13 @@ static func to_texture(from_curve: Curve, width := 256) -> CurveTexture: return texture +static func set_curve_preset(curve_to_edit: Curve, preset_index: int) -> void: + curve_to_edit.clear_points() + var preset_points: Array = presets[preset_index].values()[0] + for point: CurvePoint in preset_points: + curve_to_edit.add_point(point.pos, point.left_tangent, point.right_tangent) + + func set_default_curve() -> void: if not is_instance_valid(curve): curve = Curve.new() @@ -256,10 +263,7 @@ func _on_resize() -> void: func _on_presets_item_selected(index: int) -> void: - curve.clear_points() - var preset_points: Array = presets[index].values()[0] - for point: CurvePoint in preset_points: - curve.add_point(point.pos, point.left_tangent, point.right_tangent) + set_curve_preset(curve, index) curve = curve # Call setter